pwn常见函数简记

pwn题做多了,总是会遇到一些奇形怪状的函数,有的时候久了没看又会忘掉,就开篇专门来记一下这些东西吧

strtoul()

头文件:#include

strtoul() 函数源自于“string to unsigned long”,用来将字符串转换成无符号长整型数(unsigned long),其原型为:

unsigned long strtoul (const char* str, char** endptr, int base);

【参数说明】str 为要转换的字符串,endstr 为第一个不能转换的字符的指针,base 为字符串 str 所采用的进制。

【函数说明】strtoul() 会将参数 str 字符串根据参数 base 来转换成无符号的长整型数(unsigned long)。参数 base 范围从2 至36,或0。参数 base 代表 str 采用的进制方式,如 base 值为10 则采用10 进制,若 base 值为16 则采用16 进制数等。

strtoul() 会扫描参数 str 字符串,跳过前面的空白字符(例如空格,tab缩进等,可以通过 isspace() 函数来检测),直到遇上数字或正负符号才开始做转换,再遇到非数字或字符串结束时(‘\0’)结束转换,并将结果返回。

两点注意: 当 base 的值为 0 时,默认采用 10 进制转换,但如果遇到 ‘0x’ / ‘0X’ 前置字符则会使用 16 进制转换,遇到 ‘0’ 前置字符则会使用 8 进制转换。 若 endptr 不为NULL,则会将遇到的不符合条件而终止的字符指针由 endptr 传回

若 endptr 为 NULL,则表示该参数无效,或不使用该参数。

【返回值】返回转换后的无符号长整型数

如果不能转换或者 str 为空字符串,那么返回 0;

如果转换得到的值超出unsigned long int 所能表示的范围,函数将返回 ULONG_MAX(在 limits.h 头文件中定义),并将 errno 的值设置为 ERANGE。

如果 我们在调用这个函数的时候,有这么一段的程序

fgets(&s, 24, stdin);
v0 = strtoul(&s, 0LL, 0);

如果我们的输入为“ -1”,由于stroul函数扫描str的时候会跳过空格
那么v0是会被赋值为-1的,对于unsigned的数值来说,会造成整数溢出
而如果将v0作为一个数组的下标,就会造成数组下标的溢出

snprintf()

snprintf(),函数原型为int snprintf(char *str, size_t size, const char *format, …) 将可变个参数(…)按照format格式化成字符串,然后将其复制到str中 (1) 如果格式化后的字符串长度 < size,则将此字符串全部复制到str中,并给其后添加一个字符串结束符(‘\0’); (2) 如果格式化后的字符串长度 >= size,则只将其中的(size-1)个字符复制到str中,并给其后添加一个字符串结束符(‘\0’),返回值为欲写入的字符串长度。

补充一下,snprintf的返回值是欲写入的字符串长度,而不是实际写入的字符串度。如:

char test[8];
int ret = snprintf(test,5,"1234567890");
printf("%d|%s/n",ret,test);

运行结果为:
10|1234
可以看到ret的值实际上可以大于test[8]的长度的,如果将它作为数组的下标,则会造成漏洞

signal()

C 库函数 void (signal(int sig, void (func)(int)))(int) 设置一个函数来处理信号,即带有 sig 参数的信号处理程序

下面是 signal() 函数的声明:

void (signal(int sig, void (func)(int)))(int)

简单来说,这个函数的作用是,在出现signal信号(比如中断)的时候进行处理,一般放在初始化函数里面,有的时候需要细心留意signa函数中的处理函数参数,说不定程序的解题思路正是造成崩溃后执行其他函数

这里贴几个常见的signal信号含义:

Linux支持的信号列表如下。很多信号是与机器的体系结构相关的
信号值 默认处理动作 发出信号的原因
SIGHUP 1 A 终端挂起或者控制进程终止
SIGINT 2 A 键盘中断(如break键被按下)
SIGQUIT 3 C 键盘的退出键被按下
SIGILL 4 C 非法指令
SIGABRT 6 C 由abort(3)发出的退出指令
SIGFPE 8 C 浮点异常
SIGKILL 9 AEF Kill信号
SIGSEGV 11 C 无效的内存引用
SIGPIPE 13 A 管道破裂: 写一个没有读端口的管道
SIGALRM 14 A 由alarm(2)发出的信号
SIGTERM 15 A 终止信号
SIGUSR1 30,10,16 A 用户自定义信号1
SIGUSR2 31,12,17 A 用户自定义信号2
SIGCHLD 20,17,18 B 子进程结束信号
SIGCONT 19,18,25 进程继续(曾被停止的进程)
SIGSTOP 17,19,23 DEF 终止进程
SIGTSTP 18,20,24 D 控制终端(tty)上按下停止键
SIGTTIN 21,21,26 D 后台进程企图从控制终端读
SIGTTOU 22,22,27 D 后台进程企图从控制终端写

execlp()

头文件:#include

定义函数:int execlp(const char * file, const char * arg, …);

函数说明:execlp()会从PATH 环境变量所指的目录中查找符合参数file 的文件名, 找到后便执行该文件, 然后将第二个以后的参数当做该文件的argv[0], argv[1], …, 最后一个参数必须用空指针(NULL)作结束

返回值:如果执行成功则函数不会返回, 执行失败则直接返回-1, 失败原因存于errno 中.

简单来说,这个函数能直接执行PATH环境变量下的命令,如果配合vim使用得当,甚至可以直接进行cat flag或者getshell的操作


持续填坑ing。。。。