memset 函数

  • 函数原型:void *memset(void *str, int c, size_t n)
  • 主要功能:复制字符 c(一个无符号字符)到参数 str 所指向的字符串的前 n 个字符
  • C/C++ 实现:
#include <string.h>
#include <iostream>
#include <stdio.h>
using namespace std; int main(int argc, char ** argv)
{
char str[20] = "AAAAAAAAA";
memset(str, 'v', 10);
cout << str << endl;
return 0;
}
  • 以上程序的作用是循环复制 10 个字符 ‘v’ 到 str 所指向的字符串,执行结果:

  • 函数运行步骤:

  • 逆向分析:这个函数的作用主要是将特定的字符覆盖规定的字符串,所以首先需要取出传入 memset 函数的三个参数,并且判断第三个和第二个参数是否为 0。如果第三个参数为 0,则直接返回第一个参数所指向的字符串的首地址;如果第二个参数为 0 且第三个参数小于 100,则程序继续往下执行,反之跳出函数进行错误处理

  • 之后判断第三个参数是否小于 4,为什么要进行这个判断呢,这个先不说答案在下面。然后判断参数一传入的字符串地址是否数据对齐,如果没有对齐就对其进行对齐操作

  • 对齐判断后就开始复制字符串了,值得注意的是这里复制字符串的方式并不是循环复制 1 个字节,而是 4 个字节 4 个字节的复制,最后剩余的再每次 1 个字节的循环复制。比如我要复制 10 个字节,先循环两次复制 8 个字节,最后循环两次每次复制 1 个字节,还记得上面判断第三个参数为什么小于 4 吗,因为小于 4 的话就不必要每次 4 个字节的复制了,直接跳转到每次复制 1 个字节处即可



  • 最后将覆盖完的字符串首地址放入 eax 中,函数返回

  • 总结:memset 流程图

strcpy 函数

  • 函数原型: char *strcpy(char *dest, const char *src)
  • 作用:把 src 所指向的字符串复制到 dest
  • C/C++ 实现:
#include <string.h>
#include <iostream>
#include <stdio.h>
using namespace std; int main(int argc, char ** argv)
{
char str[20] = "AAAAAAAAA";
strcpy(str, "BBBBBB");
cout << str << endl;
return 0;
}
  • 以上程序的主要作用是将 “BB…” 复制到 str 字符串中,运行结果如图所示

  • 函数运行步骤

  • 逆向分析:首先取出传入 strcpy 函数的第一个和第二个参数



  • 之后判断第二个参数所指向的字符串是否数据对齐

  • 由于 0040121B 并不是 4 的倍数,显然数据没有对齐,从而发生跳转,进行数据对齐操作

注:对第二个参数的字符串是如何进行数据对齐操作的呢?方法简单,每次从第二个参数取出一个字符存入第一个参数指向的字符串的地址,并且第二个字符串指针加一,之后再次判断第二个参数的字符串地址是否数据对齐,如果还没有对齐就循环上述操作,直到数据对齐完毕

  • 进行完数据对齐操作之后,将第二个参数所指向的字符串循环每次复制 4 个字节到第一个参数所指向的字符串 + 2 的地址中(因为进行了对齐操作),直到这 4 个字节当中不包含 00 标志(00 表示字符串结尾)

  • 由于下面 4 个字节包含 00 字符,所以只是复制了一次

  • 最后计算出 00 字符处于 4 个字节的哪一个位置,如图所示处于第 4 个位置,故发生跳转

  • 之后把 00 字符串传入 edi 所指向的内存地址

  • 寄存器状态和内存分布如图所示:



  • strcpy 函数的流程图:

strcmp 函数

  • 函数原型:int strcmp(const char *str1, const char *str2)
  • 函数功能:把 str1 所指向的字符串和 str2 所指向的字符串进行比较(按字符的 Ascii 码进行比较)
  • C/C++ 实现:
#include <stdio.h>
#include <string.h> int main ()
{
char str1[15];
char str2[15];
int ret; strcpy(str1, "AAAaaa");
strcpy(str2, "AAaaaa"); ret = strcmp(str1, str2); if(ret < 0)
{
printf("str1 小于 str2");
}
else if(ret > 0)
{
printf("str1 大于 str2");
}
else
{
printf("str1 等于 str2");
}
return(0);
}
  • 以上程序的功能十分简单,比较 str1 和 str2 的大小,并且打印出结果。运行结果如图所示:

  • strcmp 函数运行步骤:

  • 逆向分析:首先进入 strcmp 函数,之后会取出传入 strcmp 函数的两个参数,也就是 str1 和 str2,取完参数之后判断 str1 字符串是否数据对齐,数据对齐就是 str1 字符串的首地址是否为 4 的倍数,如果 str1 字符串没有数据对齐,那么就会跳转到 0x7571938C 的地方进行数据对齐操作,在数据完成对齐后会 jmp 到 0x7571934E 的地址继续往下执行

  • 从寄存器可以看出 ecx 储存的是 str2 字符串的首地址,而 edx 储存的是 str1 字符串的首地址

  • 接下来取 str1 字符串的头四个字节放在 eax 中,之后按一个字节的大小分别与 str2 字符串相应的字符做大小比较,如果不相等就发生跳转,需要注意的时,这里比较的是 ascii 码的大小,比如 ‘A’ 字符 ascii 码为 41,而 ‘a’ 字符 ascii 码为 61,这样的话 ‘a’ 就会比 ‘A’ 字符大

  • 由于 str1 是 ‘AAAaaa’,而 str2 是 ‘AAaaaa’,所以在第三个字符比较时由于 A != a,故发生了跳转,如果前四个字节都相等的话,会将 str1 和 str2 的指针都向后指 4 个字节,在循环以上过程进行比较

  • 值得注意的是如果字符判断相等之后,如果发现 str1 对应的字符为 0(字符串结尾标志),就都会跳转到 0x75719380 这个地址,并且函数返回 0,表示字符串相等
  • 比如 str1 为 ‘Aaa’,str2 为 ‘Aaaaaa’,由于 str1 的第四个字符为 0,而前面的字符又和 str2 相等,所以判断 str1 等于 str2;但是如果 str1 为 ‘Aaaa’,而 str2 为 ‘Aaa’ 的话,则 str1 大于 str2,因为进行结尾比较的是 str1 而不是 str2,所以 str1 大于 str2

  • 最后根据 CF 标志位,以 sbb 计算的结果作为函数的返回值,如图所示 eax 的值为负数,根据 strcmp 函数的返回值文档可以看出如果函数返回值小于 0,则表示第一个参数字符串小于第二个参数字符串,也就是 str1 小于 str2

  • 为什么通过 sbb 操作指令和 CF 标志位能判断出字符串的大小呢,比如 str1 = ‘AAAA’,而 str2 = ‘AAAaaaBB’,由于前三个字符相等所以比较第四个字符,str1 的第四个字符为 A(ascii:41),而 str2 的第四个字符为 a(ascii:61),所以比较的指令就为 cmp 41,61,而 cmp 指令是根据两个操作数相减去影响标志位的,所以 41 - 61 就为负数,导致数据溢出位 CF 变为 1,而 sbb eax,eax 指令就相当于 eax - eax - CF,所以也就能比较字符的大小了
  • 那就有人问了,假如大于的话,CF 就为 0 了,岂不是两个字符串相等了吗,其实不会这样的因为在最后使用了 add eax,0x1 的操作,所以只要是大于的话返回值就会为 1,避免了和 0 之间的冲突(shl eax,1 也是同样的道理,为的是避免 add eax,0x1 在负数加一之后和 0 引发冲突)

逆向 memset、strcpy、strcmp 函数到此结束,如有错误,欢迎指正

逆向 string.h 函数库 memset、strcpy、strcmp 函数的更多相关文章

  1. 实现字符串函数,strlen(),strcpy(),strcmp(),strcat()

    实现字符串函数,strlen(),strcpy(),strcmp(),strcat() #include<stdio.h> #include<stdlib.h> int my_ ...

  2. numpy函数库中一些常用函数的记录

    ##numpy函数库中一些常用函数的记录 最近才开始接触Python,python中为我们提供了大量的库,不太熟悉,因此在<机器学习实战>的学习中,对遇到的一些函数的用法进行记录. (1) ...

  3. 逆向 string.h 函数库 strlen、memchr、strcat 函数

    strlen 函数 主要功能:返回字符串的长度 C/C++ 实现: #include <iostream> #include <stdio.h> #include <st ...

  4. 逆向 time.h 函数库 time、gmtime 函数

    0x01 time 函数 函数原型:time_t time(time_t *t) 函数功能:返回自纪元 Epoch(1970-01-01 00:00:00 UTC)起经过的时间,以秒为单位.如果 se ...

  5. C语言中的string.h中的内存字符串处理函数

    转载请注明出处:http://blog.csdn.net/zhubin215130/article/details/8993403 void *memcpy(void *dest, const voi ...

  6. 自己实现字符串操作函数strlen(),strcat(),strcpy(),strcmp()

    1.strlen()函数是求解字符串的有效长度的 1)非递归实现 size_t my_strlen(const char *str) { assert(str != NULL);  //断言,保证指针 ...

  7. Mysql 常用函数(10)- strcmp 函数

    Mysql常用函数的汇总,可看下面系列文章 https://www.cnblogs.com/poloyy/category/1765164.html strcmp 的作用 比较两个字符串的顺序是否完全 ...

  8. 使用c函数库的两个函数strtok, strncpy遇到的问题记录

    1. strtok 问题背景: 解析形如 “1,2,3,4,5”字符串到整数数组 (1)计算个数 char* delim = ","; int count = 0; int *nu ...

  9. 13-C语言字符串函数库

    目录: 一.C语言字符串函数库 二.用命令行输入参数 回到顶部 一.C语言字符串函数库 1 #include <string.h> 2 字符串复制 strcpy(参数1,参数2); 参数1 ...

随机推荐

  1. JDBC 连接池 & Template

    数据库连接池 # 概念:其实就是一个容器(集合),存放数据库连接的容器. * 当系统初始化号以后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库时,从容其中获取连接对象,用户访问完之后,会将 ...

  2. 选择 FreeBSD 而不是 Linux 的技术性原因3

    选择 FreeBSD 而不是 Linux 的技术性原因3 jail FreeBSD Jails 系统是另一个惊人的工程壮举. 在 2000 年 3 月 14 日的 4.0 版本中,FreeBSD 引入 ...

  3. 从RocketMQ的Broker源码层面验证一下这两个点

    本篇博客会从源码层面,验证在RocketMQ基础概念剖析,并分析一下Producer的底层源码中提到的结论,分别是: Broker在启动时,会将自己注册到所有的NameServer上 Broker在启 ...

  4. C# 通过ServiceStack 操作Redis——List类型的使用及示例

    Redis list的实现为一个双向链表,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销, /// <summary> /// Redis list的实现为一个双向链表 ...

  5. 振兴中华(蓝桥杯13年第四届省赛真题 JAVA-B组)

    思路:因为只能横向或纵向跳到相邻的格子里,所以到'华'字有两种方法:①从左边的中横向跳过来 ②从上边的中纵向跳过来 直接递推即可. 标题: 振兴中华 小明参加了学校的趣味运动会,其中的一个项目是:跳格 ...

  6. 循环3n加1问题

    package 第二章; import java.util.Scanner; //int 32位整数 /*  * 猜想:对于任意大于一的自然数n,若n为奇数,则将n变为3n+1,否则变为n的一半 经过 ...

  7. Spring工程搭建

    创建Maven项目 1.下载Maven资源包 http://maven.apache.org/download.cgi 2.打开IDEA创建Maven项目 在新建项目窗口选择Maven项目:检查当前S ...

  8. java例题_13 加上100再加上168的完全平方数问题

    1 /*13 [程序 13 根据条件求数字] 2 题目:一个整数,它加上 100 后是一个完全平方数,再加上 268 又是一个完全平方数,请问该数是多少? 3 程序分析:在 10万以内判断,先将该数加 ...

  9. java进阶(41)--反射机制

    文档目录: 一.反射机制的作用 二.反射机制相关类 三.获取class的三种方式 四.通过反射实例化对象 五.通过读属性文件实例化对象 六.通过反射机制访问对象属性 七.通过反射机制调用方法 ---- ...

  10. 幻灯片放映模式切换windows terminal背景图片

    目录 幻灯片放映模式切换windows terminal背景图片 脚本功能 开发需求 使用技术 操作说明 使用示例 查看帮助 输入参数使用 脚本详情 引用参考 幻灯片放映模式切换windows ter ...