出于好奇,探究下scanf汇编怎么工作的,练习下思路。
// func_scanf.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
int main(int argc, char* argv[])
{
char password[1024];
printf("please input password: ");
scanf("%s\n",password);
printf("what you input is %s",password);
return 0;
}
关于怎么找main函数另一篇文章提到了寻找特征的方法…这里直接过
至此的操作是申请用于main函数的变量空间以及保存现场(push ebx,esi,edi),操作于此前文章一样的操作,不做过多赘述。。。
看注释,很明显对应我们源代码的:printf("please input password: ");不过这里是将字符串入栈,后面再call printf函数完成调用。函数调用方式之前也提到了,哈哈
做下细节,养成查看不太清楚的地址等的操作,跟随push的地址,再数据窗口,我们可以看到:
证实了我们的猜测,入栈的是printf函数调用的参数。printf函数的学习不是本文的主题,下图为call printf
调用的同时,入栈call下条指令的地址用于返回(执行完printf可以返回到这句执行,pop出这个地址),也就是下面这句:
将栈顶下降…接下来执行这句:
取[local.256]的地址给eax,这里估计是main申请的变量空间我们跟随下内存:
发现全是CC,我们猜测应该没错,此前对申请的空格键进行初始化,就是用的CC填充
接下来的指令是:
将EAX(即main申请到的变量空间地址)入栈,再push 了一个地址,我们再次跟进:
总体发现,其实也就对应了源代码中的: scanf("%s\n",password); 也就是我们的研究对象,scanf函数,call是还是一样,入栈add esp,0x8这条指令的地址,
我们F7步入该函数:
堆栈紫色对应call前下条指令地址:0040104C 往下则是scanf参数,一个是占位符%s,一个是用于存放字符串的地址估计scanf的函数原型需要一个指针作为参数
确实也是有个指针参数,哈哈。
进到scanf函数…:
看到了ebp入栈…更新ebp…抬高esp的操作…又是函数局部变量的申请…
后面的lea eax,[arg.2],跟随后发现其实就是之前入栈的空间地址…
接下来世这个,就是把取到的地址放到[local.1]里面,其实就是scanf函数前面申请的变量空间,(ebp-4)
cmp 指令加转移指令,很典型的条件控制跳转了,这里的[arg.1]是占位符%s的栈位置,和0进行cmp指令,很显然,Z标志位是0
后面的jnz指令检查的是Z标志位,当为0则跳转,我们跟随跳转:
首先操作的是清空ecx…又是组合指令条件判断跳转》。。
test ecx,ecx改变Z标志位为1,跳转仍然不成立,继续执行
把[local.1](存放main申请用来保存password变量的空间地址)付给edx:
占位符地址的赋给eax
这里不想跟了》。。大概是从键盘读取输入并存到内存空间(之前的地址参数)吧…再跟好累…
回到终端,输入…
输完,跟踪此前作为参数的地址参数,我们可以看到我们的输入写入到内存了…
执行完后,又回到main这边…至此scanf函数汇编讲解就到这里了,需要消化…其实也就是好奇工作原理…