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
函数将返回零
失败:返回非零值