随笔三

read函数

1
ssize_t read(int fd, void *buf, size_t count);
参数 意义
fd 文件描述符,用来指向要操作的文件的文件结构体
buf 一块内存空间
count 希望读取的字节数

fd为0时表示键盘输入
返回值表示实际读到的字节数(字符串结束符 ‘\0’不算,但是包括换行符)

write函数

1
ssize_t write (int fd, const void * buf, size_t count);

参数作用与read函数相似,一个是读文件,一个是写文件
fd为1时,是向显示器输出指定指定地址内容

setbuf函数

1
void setbuf(FILE * stream, char * buf);

函数setbuf()用于将指定缓冲区与特定的文件流相关联,实现操作缓冲区时直接操作文件流的功能。
stream为文件流指针,buf为缓冲区的起始地址

1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>  
char outbuf[BUFSIZ];
int main(void)
{
setbuf(stdout, outbuf); // 把缓冲区与流相连
puts("This is a test of buffered output.\n");
puts(outbuf); //此时并不会输出到显示器
fflush(stdout); // 刷新,此时会输出缓存内容
puts(outbuf); // 输出
return 0;
}

输出结果:
This is a test of buffered output..
This is a test of buffered output..
This is a test of buffered output..
This is a test of buffered output..

程序先把outbuf与输出流相连,然后输出一个字符串,这时因为缓冲区已经与流相连,所以outbuf中也保存着这个字符串,紧接着puts函数又输出一遍,所以现在outbuf中保存着两个一样的字符串。刷新输出流之后,再次puts,则又输出两个字符串。

setbuf(stdout,0)作用就是不设置缓冲区,使得外来用户使用nc访问时,可以收到输出的字符串,否则将无法收到输出的字符串

recvall

recvall为pwntools内置函数,可以接受所有字符串,直到EOF

堆栈溢出原理

关于堆栈溢出可参考文章堆栈溢出原理
补充说明: ebp总是指向调用函数的ebp值,ebp的下一位高低之总是指向函数返回地址,之后依次是函数的参数,参数从左至右,从低到高
特别是当ebp所指向的原ebp地址无效时,ebp首先跳转到无效地址,当我们修改了函数返回地址后,就是调用一个新的函数,而在调用新函数时,每个函数的开头总会有几句汇编指令

1
2
3
push ebp
mov ebp,esp
sub esp,xxx

这几句汇编指令可以使得ebp恢复正常值,此时ebp的值的是原来函数栈存放返回地址的地址(push ebp后esp的值),而指向的值是我们输入的无效ebp值

byte,word,dword,qword

一、 32位程序

类型 大小
BYTE 8bit
WORD 16bit
DWORD 32bit
QWORD NULL
32bit

二、 64为程序

类型 大小
BYTE 8bit
WORD 16bit
DWORD 32bit
QWORD 64bit
64bit

shellcode

1
2
64位: \x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05
32位: \x99\x6a\x0b\x58\x60\x59\xcd\x80

pwntools

关于pwntools的使用可以参考pwntoolshttps://bbs.pediy.com/thread-247217.htm

ELF类

ELF类是pwn中的一个类

1
2
3
4
5
6
7
elf=ELF('./level3')

#获取函数地址
write_plt = elf.plt['write'] # 获取plt表中write函数在程序中的地址
write_got = elf.got['write'] # 获取got表中write函数在程序中的地址
main_addr = elf.symbols['main'] # 获取main函数在程序中的地址
# 一般获取程序自带的函数地址用symbols()查找,而对于外部函数则查询plt,got表的地址

strings的使用

strings命令在对象文件或二进制文件中查找可打印的字符串。
字符串是4个或更多可打印字符的任意序列,以换行符或空字符结束。
strings命令对识别随机对象文件很有用。

语法

strings [ -a ] [ - ] [ -o ] [ -t Format ] [ -n Number ] [ -Number ] [ file … ]

参数

-a –all:扫描整个文件而不是只扫描目标文件初始化和装载段
-f –print-file-name:在显示字符串前先显示文件名
-n –bytes=[number]:找到并且输出所有NUL终止符序列
-t –radix={o,d,x} :输出字符的位置,基于八进制,十进制或者十六进制
-o :类似–radix=o
-T –target= :指定二进制文件格式
-e –encoding={s,S,b,l,B,L} :选择字符大小和排列顺序:s = 7-bit, S = 8-bit, {b,l} = 16-bit, {B,L} = 32-bit
@ :读取中选项

实例
查找ls中包含libc的字符串,不区分大小写:

1
strings /bin/ls | grep -i libc

‘|’符号

|符号前面的命令执行的结果作为操作对象传递给符号后的命令

grep

grep(global search regular expression(RE) and print out the line,全面搜索正则表达式并把行打印出来)是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的打印出来。

关于其用法可以参考grep命令