IDA中的一些C语言函数
readfsqword
__readfsqword(0x28u)——canary 保护机制,防止调试
- 程序开始时,定义 - v6 = __readfsqword(0x28u)
- 程序结束时,通过异或或者其他手段检测 - v6的值是否发生改变
- 若该值发生改变,则程序终止运行 
alarm
unsigned int alarm(unsigned int seconds)——设置信号传送闹钟,干扰调试
- 用来设置信号 - sigalrm在经过参数- seconds秒数后发送给目前的进程
 如果未设置信号- sigalrm的处理函数,那么- alarm()默认处理终止进程
- 如果在 - seconds秒内再次调用了- alarm函数设置了新的闹钟,则后面定时器的设置将覆盖前面的设置,即之前设置的秒数被新的闹钟时间取代
 当参数- seconds为 0 时,之前设置的定时器闹钟将被取消,并将剩下的时间返回
read
ssize_t read(int fd, void *buf, size_t count)——用于从文件描述符对应的文件中读取数据
| 参数 | 意义 | 
|---|---|
| fd | 文件描述符, 从 command line 获取数据时,为 0 | 
| buf | 读出数据的缓冲区 | 
| count | 每次读取的字节数(是请求读取的字节数,读上来的数据保存在缓冲区 buf 中,同时文件的当前读写位置向后移) | 
- 返回值: - 成功:返回读出的字节数
- 失败:返回 -1,并设置 errno。如果在调用 read之前到达文件末尾,则这次read返回 0
 
- read 函数可以取代 scanf 从 command line 读取数据 
fread
size_t fread(void *ptr, size_t size, size_t count, FILE *stream)——从指定的文件中读取一定数量的数据,并将其存储到指定的内存位置
| 参数 | 意义 | 
|---|---|
| ptr | 指向要存储读取数据的内存块的指针 | 
| size | 要读取的每个数据项的大小(以字节为单位) | 
| count | 要读取的数据项的数量 | 
| stream | 文件指针,指向要从中读取数据的文件 | 
- fread()函数可用于二进制文件和文本文件。对于文本文件,由于可能存在换行符和不可见字符,使用- fread()函数读取时需要小心,以免导致错误的结果
- 需要确保读取的数据 - count不超过目标数组的大小,以避免溢出。
- 返回值: - fread()函数返回实际成功读取的数据数目,如果返回值小于- count,可能已经达到文件末尾或发生了错误
write
ssize_t write(int fd,const void *buf,size_t count)——用于将数据写入到文件描述符对应的文件
| 参数 | 意义 | 
|---|---|
| fd | 文件描述符(输出到 command line,就是 1) | 
| buf | 通常是一个字符串,需要写入的字符串 | 
| count | 每次写入的字节数 | 
- 返回值: - 成功:返回写入的字节数
- 失败:返回 -1,并设置 errno
 
- write 函数可以代替 printf,往 command line 打印输出 
memset
void *memset(void *str, int ch, size_t n)——用于非常量的内存空间初始化
- 复制字符 - ch(一个无符号字符)到参数- str所指向的字符串的前 n 个字符
- 将 - str中当前位置后面的 n 个字节 用- ch替换并返回- str,- ch只有最低的字节起作用
- 作用是将某一块内存中的内容全部设置为指定的值, 这个函数通常为新申请的内存做初始化工作 
atoi
int atoi(const char *str)——把参数 str 所指向的字符串转换为一个整数(类型为 int 型)
- 该函数返回转换后的长整数,如果没有执行有效的转换,则返回零 
- 示例: 
- 结果: 
atol
long int atol(const char *str)——把参数 str 所指向的字符串转换为一个长整数(类型为 long int 型)
- 该函数返回转换后的长整数,如果没有执行有效的转换,则返回零
setvbuf
int setvbuf(FILE *stream, char *buffer, int mode, size_t size)——定义流 stream 应如何缓冲,把缓冲区与流相关
- 如果成功,则该函数返回 0,否则返回非零值
errno_location
int *__errno_location(void)——返回当前线程的变量地址
- 这个函数的返回值是一个函数指针,这个指针指向线程自己的 errno 的位置,通过对这个指针解引用,就可以访问线程唯一的 errno 
- errno 是 error number 的缩写,意味系统调用错误码 
 如果系统调用返回成功,errno 有可能但不一定会置 0;而系统调用出错时,errno 必定会被设为对应的错误编号
malloc
void *malloc(size_t size)——分配所需的内存空间,并返回一个指向它的指针
- size为内存块的大小,以字节为单位
- 该函数返回一个指针 ,指向已分配大小的内存。如果请求失败,则返回 NULL 
calloc
void *calloc(size_t nitems, size_t size)——分配所需的内存空间,并返回一个指向它的指针
| 参数 | 意义 | 
|---|---|
| nitems | 要被分配的元素个数 | 
| size | 元素的大小 | 
- 该函数返回一个指针,指向已分配的内存。如果请求失败,则返回 NULL 
- malloc和- calloc之间的不同点:
 malloc 不会设置内存为零;而 calloc 会设置分配的内存为零
gmpz_init_set_str(等同于 mpz_init_set_str)
int mpz_init_set_str (mpz_t rop, char *str, int base)——将 str 字符数组以 base 指定的进制解读成数值并写入 rop 所指向的内存GMP 又叫 GNU 多精度算术库,是一个提供了很多操作高精度的大整数、浮点数运算的算术库,几乎没有什么精度方面的限制,功能丰富
- 这三个参数分别是:
| 参数 | 意义 | 
|---|---|
| rop | 多精度整数变量 | 
| str | 字符串 | 
| base | 进制 | 
- 示例:mpz_powm(op1,op2,op3,op4); // 求幂模函数,即:op1 = op2 ^ op3 mod op4
gmpz_powm(等同于 mpz_powm)
void mpz_powm (mpz_t rop, const mpz_t base, const mpz_t exp, const mpz_t mod)——计算 base 的 exp 次方,并对 mod 取模,最后将结果写入 rop 中
- 运算的过程和 RSA 的加密过程一样 
- 示例: - mpz_init_set_str(b, “200000”, 10); // 即:b=200000,十进制
gmpz_cmp(等同于 mpz_cmp)
mpz_cmp(mpz_t num1, mpz_t num_2)——比较两个数
- 示例:mpz_cmp(b, c); // 若 b 大于 c,返回1;若 b 等于 c,返回0;若 b 小于 c,返回-1
strcat
char *strcat(char *dest, const char *src)——把 src 所指向的字符串追加到 dest 所指向的字符串的结尾
| 参数 | 意义 | 
|---|---|
| dest | 指向目标数组,该数组包含了一个 C 字符串,且足够容纳追加后的字符串 | 
| src | 指向要追加的字符串,该字符串不会覆盖目标字符串 | 
- 该函数返回一个指向最终的目标字符串 dest的指针
time
time_t time(time_t *timer)——得到当前日历时间或者设置日历时间
- 参数说明: - timer = NULL时得到当前日历时间(从 1970-01-01 00:00:00 到现在的秒数)- timer = 时间数值时,用于设置日历时间,- time_t是一个 unsigned long 类型
 如果- timer不为空,则返回值也存储在变量- timer中
- 函数返回:当前日历时间 
localtime
struct tm *localtime(const time_t *timer)——使用 timer 的值来填充 tm 结构。timer 的值被分解为 tm 结构,并用本地时区表示
- timer是指向表示日历时间的- time_t值的指针
- 该函数返回指向 - tm结构的指针,该结构带有被填充的时间信息
- tm结构的细节:
struct tm {
   int tm_sec;         /* 秒,范围从 0 到 59 */
   int tm_min;         /* 分,范围从 0 到 59 */
   int tm_hour;        /* 小时,范围从 0 到 23 */
   int tm_mday;        /* 一月中的第几天,范围从 1 到 31 */
   int tm_mon;         /* 月份,范围从 0 到 11 */
   int tm_year;        /* 自 1900 起的年数 */
   int tm_wday;        /* 一周中的第几天,范围从 0 到 6 */
   int tm_yday;        /* 一年中的第几天,范围从 0 到 365 */
   int tm_isdst;       /* 夏令时 */    
};pthread_create
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg)——用来创建线程,在线程创建以后,就开始运行相关的线程函数
| 参数 | 意义 | 
|---|---|
| pthread_t *thread | 新创建的线程 ID 指向的内存单元。pthread_t 是一种用于表示线程的数据类型,每一个 pthread_t 类型的变量都可以表示一个线程 | 
| const pthread_attr_t *attr | 用于手动设置新建线程的属性,例如线程的调用策略、线程所能使用的栈内存的大小等。大部分场景中,我们都不需要手动修改线程的属性,将 attr 参数赋值为 NULL,pthread_create() 函数会采用系统默认的属性值创建线程 | 
| void *(*start_routine) (void *) | 新创建的线程从 start_rtn 函数的地址开始运行。形参和返回值的类型都必须为 void* 类型 | 
| void *arg | 指定传递给 start_routine 函数的实参,当不需要传递任何数据时,将 arg 赋值为 NULL 即可 | 
- 如果成功创建线程,pthread_create() 函数返回数字 0,反之返回非零值
- 各个非零值都对应着不同的宏,指明创建失败的原因,常见的宏有以下几种:- EAGAIN:系统资源不足,无法提供创建线程所需的资源
- EINVAL:传递给 pthread_create() 函数的 attr 参数无效
- EPERM:传递给 pthread_create() 函数的 attr 参数中,某些属性的设置为非法操作,程序没有相关的设置权限
 
pthread_join
int pthread_join(pthread_t thread, void * * retval)——获取某个线程执行结束时返回的数据
| 参数 | 意义 | 
|---|---|
| thread | 指定接收哪个线程的返回值 | 
| retval | 接收到的返回值。如果 thread 线程没有返回值,或者不需要接收 thread 线程的返回值,可以将 retval 参数置为 NULL | 
- pthread_join()函数会一直阻塞调用它的线程,直至目标线程执行结束(接收到目标线程的返回值),阻塞状态才会解除
- 如果 pthread_join()函数成功等到了目标线程执行结束(成功获取到目标线程的返回值),返回值为数字 0;反之如果执行失败,函数会根据失败原因返回相应的非零值,每个非零值都对应着不同的宏,例如:- EDEADLK:检测到线程发生了死锁
- EINVAL:分为两种情况,要么目标线程本身不允许其它线程获取它的返回值,要么事先就已经有线程调用 pthread_join() 函数获取到了目标线程的返回值
- ESRCH:找不到指定的 thread 线程
 
fseek
int fseek(FILE *stream, long offset, int origin)——用于移动文件指针到指定的位置,从而在文件中进行随机访问或定位
| 参数 | 意义 | 
|---|---|
| stream | 文件指针,指向要操作的文件 | 
| offset | 文件指针偏移量,即要移动的字节数 | 
| origin | 指定参考位置,可以是以下常量之一: SEEK_SET:从文件开头开始计算偏移 SEEK_CUR:从当前位置开始计算偏移 SEEK_END:从文件末尾开始计算偏移 | 
- fseek()函数可用于二进制文件和文本文件。对于文本文件,由于可能存在换行符和不可见字符,使用- fseek()函数移动文件指针时需要小心,以免导致错误的结果
- 返回值: 
 成功:- fseek函数将返回零
 失败:返回非零值












