0%

xdbg食品检测记录之五

串相关

strcmp

strcmp的作用就是两个串之间的比较,如下为编写的源代码

如下为主函数

其中可以看见在未执行strcmp的时候往栈中存入了两个串的地址,同时又转换存入寄存器方便调用

如下为strcmp函数部分

首先是取出地址部分然后检测地址是否为空,后续是进行的循环:首先test al, al来判断al是否为空,也就是是否为串的结束部分,不为空继续往后比较大小(shr eax, 10),大小一样继续比较后面,不一样则跳转执行具体的大小比较(jne ucrtbase.76FB1C48)。循环也就是靠jne ucrtbase.76FB1C10做到,这里的地址就是我们在确定地址不为空的test edx, 3后一句的后一句的地址。
这里的test指令其实是将两个内容进行逻辑与的过程类似于and但是不改变两个地方的实际值,只改变寄存器。

scas & repne

scasb,scasw,scasd其实也就是对应的byte,word,dword。scasb编译后相当于cmp byte ptr [edi],al 对标志位有影响还会修改寄存器edi的值(df = 0,inc edi;df = 1,dec edi)。
代码如下,略显粗暴

未执行到scasb时

执行过scasb,edi因为df为0,inc edi

repne或者repnz都是一个意思,满足ecx != 0且 zf = 0时重复执行其后跟着的指令并将ecx减一(根据b,w,d转换地址),比如repne scasb 重复执行scasb。
稍微修改代码,主要是计数这个串的长度

刚开始时

赋值ecx,al后

每次执行scasb导致的edi增加也就是提取的串的字符往后移的过程,移到串的结束符的时候于al的值相同了,zf赋值为1,edi回移;repne不知继续循环。此时的ecx与一开始的差值再减一(结束符的长度)就是串的长度。

再改进一下代码增加减一的部分,注释掉的和写出的都可行

cmps

相较于scasb,cmpsb的区别就在于比较的是两个串scasb是寄存器和串的比较。同样有cmpsb,cmpsw,cmpsd。
代码如下,cmpsb同样可以与repne连用作为循环

刚开始

将两串赋值给esi和edi寄存器

两个串只有2和1的差距,在检测到这个地方后大小就比出来了然后跳出repne继续执行下一条指令

用cmpsb来写一个strcmp函数

以下是主函数

跳转到call strcmp的位置,这里多了一些我在代码里面没写的东西,这是编译器直接加的,如果不想要可以在前面写__declspec(naked),但是这样寄存器调用前的入栈调用后的出栈还原,堆栈的平衡都要自己写了。