0x01 环境变量
什么是环境变量?
环境变量是在操作系统中一个具有特定名字的对象,它包含了一个或者多个应用程序所将使用到的信息。
Linux环境变量分类
一、按照生命周期来分,Linux环境变量可以分为两类:
1、永久的:需要用户修改相关的配置文件,变量永久生效。
2、临时的:用户利用export命令,在当前终端下声明环境变量,关闭Shell终端失效。
二、按照作用域来分,Linux环境变量可以分为:
1、系统环境变量:系统环境变量对该系统中所有用户都有效。(在/.bash_profile中定义)
2、用户环境变量:这种类型的环境变量只对特定的用户有效。(在/etc/profile中定义)
Linux中常见的系统变量
- PATH:指定命令的搜索路径
PATH变量的声明
PATH=$PAHT:<PATH 1>:<PATH 2>:<PATH 3>:--------:< PATH n >
export PATH
- HOME:指定用户的主工作目录(即用户登陆到Linux系统中时,默认的目录)。
- HISTSIZE:指保存历史命令记录的条数。
- LOGNAME:指当前用户的登录名
- HOSTNAME:指主机的名称,许多应用程序如果要用到主机名的话,通常是从这个环境变量中来取得的
- SHELL:指当前用户用的是哪种Shell。
- LANG/LANGUGE:和语言相关的环境变量,使用多种语言的用户可以修改此环境变量。
- MAIL:指当前用户的邮件存放目录。
Linux中操作环境变量的命令
- echo 显示某个环境变量值 echo $PATH
- export 设置一个新的环境变量 export HELLO=”hello” (可以无引号)
- env 显示所有环境变量
- set 显示本地定义的shell变量
- unset 清除环境变量 unset HELLO
- readonly 设置只读环境变量 readonly HELLO
C程序调用环境变量函数
- getenv()返回指向一个环境变量的指针。
- setenv()设置一个环境变量。
- unsetenv()清除一个环境变量。
环境变量部分参考链接:https://www.jianshu.com/p/ac2bc0ad3d74
关于环境变量的详细分析 http://blog.csdn.net/reliveIT/article/details/45224575
0x02 题目分析
T1
题目源码:
题目分析:
在主函数中定义了modified(int)、buffer[64]、variable(char *)三个变量,variable获取指向HEETIAN环境变量的指针,判断非空(成功获取)后,设置modified为0,将HEETIAN环境变量的值赋给buffer。由于strcpy可引发缓冲区溢出,这道题可以使用buffer修改modified的值达到绕过验证的目的。
Payload
T2 ELF x86 - Stack buffer overflow basic 4
题目连接:rootme
程序源码:
题目分析
源码中有四个strcpy都可以产生栈溢出,我们选择距离ebp最近的PATH变量进行攻击,使用PATH变量覆盖掉GetEnv函数的入口地址(位于ebp+4处)
运行程序:
缺少username环境变量,把shellcode放在username中
使用gdb调试程序,在GetEnv函数入口处下断
运行程序,查看GetEnv函数的入口地址和path、username的地址
0xbffff66c到0xbffff70c的偏移量等于160,也就是说path的长度应该达到164,最后四个字节是目的地址。
看一下path变量原来的长度
160-109=51
需要51字节的填充
我在第二次调试时username的地址变成了0xbffff55c,而且偏移地址51会引起段错误,50正确,不知道为什么。。。(有知道的同学欢迎指教)
这时在gdb中运行会得到shell
但在shell中运行会引发段错误
思考了一下可能是因为username在gdb和在shell中运行时的地址不同造成的,在网上搜到的wp都有写了c程序获得环境变量的地址:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
char *ptr;
if(argc < 3) {
fprintf(stderr, "Usage: %s <environment var> <target program name>\n", argv[0]);
exit(1);
}
/* Get env var location. */
ptr = getenv(argv[1]);
/* Adjust for program name. */
ptr += (strlen(argv[0]) - strlen(argv[2])) * 2;
printf("%s will be at %p\n", argv[1], ptr);
}
(这段代码里我有一个不太理解的地方:为什么需要根据程序名调整ptr的值,有知道的同学欢迎指导)
编译程序
运行获取USERNAME的地址
修改PATH获得shell