首页
社区
课程
招聘
[讨论]fscanf函数的一个问题?
发表于: 2015-2-2 04:58 5064

[讨论]fscanf函数的一个问题?

2015-2-2 04:58
5064
今天写代码的时候发现一个有趣的问题,fscanf读入一个缓冲区的数据总是不完全,小生先把问题的简化代码贴一下
#include <stdio.h>
#include <windows.h>

void main()
{
  char pwd[1024]={0};
  FILE *fp=fopen("D:\\test\\1.txt", "rw+");
  fscanf(fp, "%s", pwd);
  printf("%s",pwd);
}



接一个插曲,这段代码放在vs2012中运行会出现如下错误


2012不支持w方式??


回到正文,1.txt内容如下:


在printf处下断,看下缓冲区pwd的内存


看到fscanf读到0x0e处就终止了,而文件的内容没有读完,起初我遇到这样的问题,最终定位在文件里的0x0a,后来测试一下从0d就读不进去了。我用od跟了一下,定位到从文件指针缓冲区复制数据到自定义缓冲区的代码
00405DBE  |> /83BD 18FEFFFF>|/CMP DWORD PTR SS:[EBP-1E8],0
00405DC5  |. |74 14         ||JE SHORT 1.00405DDB
00405DC7  |. |8B45 E4       ||MOV EAX,DWORD PTR SS:[EBP-1C]
00405DCA  |. |8B4D E4       ||MOV ECX,DWORD PTR SS:[EBP-1C]
00405DCD  |. |83E9 01       ||SUB ECX,1
00405DD0  |. |894D E4       ||MOV DWORD PTR SS:[EBP-1C],ECX
00405DD3  |. |85C0          ||TEST EAX,EAX
00405DD5  |. |0F84 2A010000 ||JE 1.00405F05
00405DDB  |> |8B55 E0       ||MOV EDX,DWORD PTR SS:[EBP-20]          ;  堆栈 SS:[0012FAC8]=00000001
00405DDE  |. |83C2 01       ||ADD EDX,1                              ;  2
00405DE1  |. |8955 E0       ||MOV DWORD PTR SS:[EBP-20],EDX          ;  12fac8
00405DE4  |. |8B45 08       ||MOV EAX,DWORD PTR SS:[EBP+8]
00405DE7  |. |50            ||PUSH EAX                               ; /Arg1
00405DE8  |. |E8 A30D0000   ||CALL 1.00406B90                        ; \1.00406B90
00405DED  |. |83C4 04       ||ADD ESP,4                              ;  33
00405DF0  |. |8985 28FEFFFF ||MOV DWORD PTR SS:[EBP-1D8],EAX
00405DF6  |. |83BD 28FEFFFF>||CMP DWORD PTR SS:[EBP-1D8],-1
00405DFD  |. |0F84 DF000000 ||JE 1.00405EE2
00405E03  |. |8B8D 28FEFFFF ||MOV ECX,DWORD PTR SS:[EBP-1D8]
00405E09  |. |C1F9 03       ||SAR ECX,3                              ;  1f-0
00405E0C  |. |0FBE540D A0   ||MOVSX EDX,BYTE PTR SS:[EBP+ECX-60]     ;  堆栈 SS:[0012FA8E]=00; ebp-41, ebp-60
00405E11  |. |0FBE45 F0     ||MOVSX EAX,BYTE PTR SS:[EBP-10]         ;  堆栈 SS:[0012FAD8]=FF
00405E15  |. |33D0          ||XOR EDX,EAX
00405E17  |. |8B8D 28FEFFFF ||MOV ECX,DWORD PTR SS:[EBP-1D8]         ;  堆栈 SS:[0012F910]=00000033
00405E1D  |. |83E1 07       ||AND ECX,7                              ;  3
00405E20  |. |B8 01000000   ||MOV EAX,1
00405E25  |. |D3E0          ||SHL EAX,CL                             ;  8
00405E27  |. |23D0          ||AND EDX,EAX                            ;  8
00405E29  |. |85D2          ||TEST EDX,EDX
00405E2B  |. |0F84 B1000000 ||JE 1.00405EE2
00405E31  |. |0FBE4D 90     ||MOVSX ECX,BYTE PTR SS:[EBP-70]         ;  堆栈 SS:[0012FA78]=00
00405E35  |. |85C9          ||TEST ECX,ECX
00405E37  |. |0F85 94000000 ||JNZ 1.00405ED1
00405E3D  |. |0FBE55 9C     ||MOVSX EDX,BYTE PTR SS:[EBP-64]         ;  堆栈 SS:[0012FA84]=00
00405E41  |. |85D2          ||TEST EDX,EDX
00405E43  |. |74 76         ||JE SHORT 1.00405EBB
00405E45  |. |8A85 28FEFFFF ||MOV AL,BYTE PTR SS:[EBP-1D8]
00405E4B  |. |8885 10FEFFFF ||MOV BYTE PTR SS:[EBP-1F0],AL
00405E51  |. |8B8D 28FEFFFF ||MOV ECX,DWORD PTR SS:[EBP-1D8]
00405E57  |. |81E1 FF000000 ||AND ECX,0FF
00405E5D  |. |8B15 90AE4200 ||MOV EDX,DWORD PTR DS:[42AE90]          ;  1.0042AE9A
00405E63  |. |33C0          ||XOR EAX,EAX
00405E65  |. |66:8B044A     ||MOV AX,WORD PTR DS:[EDX+ECX*2]
00405E69  |. |25 00800000   ||AND EAX,8000
00405E6E  |. |85C0          ||TEST EAX,EAX
00405E70  |. |74 1B         ||JE SHORT 1.00405E8D
00405E72  |. |8B4D E0       ||MOV ECX,DWORD PTR SS:[EBP-20]
00405E75  |. |83C1 01       ||ADD ECX,1
00405E78  |. |894D E0       ||MOV DWORD PTR SS:[EBP-20],ECX
00405E7B  |. |8B55 08       ||MOV EDX,DWORD PTR SS:[EBP+8]
00405E7E  |. |52            ||PUSH EDX                               ; /Arg1
00405E7F  |. |E8 0C0D0000   ||CALL 1.00406B90                        ; \1.00406B90
00405E84  |. |83C4 04       ||ADD ESP,4
00405E87  |. |8885 11FEFFFF ||MOV BYTE PTR SS:[EBP-1EF],AL
00405E8D  |> |A1 9CB04200   ||MOV EAX,DWORD PTR DS:[42B09C]
00405E92  |. |50            ||PUSH EAX                               ; /Arg3 => 00000001
00405E93  |. |8D8D 10FEFFFF ||LEA ECX,DWORD PTR SS:[EBP-1F0]         ; |
00405E99  |. |51            ||PUSH ECX                               ; |Arg2
00405E9A  |. |8D55 FC       ||LEA EDX,DWORD PTR SS:[EBP-4]           ; |
00405E9D  |. |52            ||PUSH EDX                               ; |Arg1
00405E9E  |. |E8 BD780000   ||CALL 1.0040D760                        ; \1.0040D760
00405EA3  |. |83C4 0C       ||ADD ESP,0C
00405EA6  |. |8B45 C4       ||MOV EAX,DWORD PTR SS:[EBP-3C]
00405EA9  |. |66:8B4D FC    ||MOV CX,WORD PTR SS:[EBP-4]
00405EAD  |. |66:8908       ||MOV WORD PTR DS:[EAX],CX
00405EB0  |. |8B55 C4       ||MOV EDX,DWORD PTR SS:[EBP-3C]
00405EB3  |. |83C2 02       ||ADD EDX,2
00405EB6  |. |8955 C4       ||MOV DWORD PTR SS:[EBP-3C],EDX
00405EB9  |. |EB 14         ||JMP SHORT 1.00405ECF
00405EBB  |> |8B45 C4       ||MOV EAX,DWORD PTR SS:[EBP-3C]          ;  堆栈 SS:[0012FAAC]=0012FB75
00405EBE  |. |8A8D 28FEFFFF ||MOV CL,BYTE PTR SS:[EBP-1D8]           ;  堆栈 SS:[0012F910]=33 ('3')
00405EC4  |. |8808          ||MOV BYTE PTR DS:[EAX],CL               ;  CL=33 ('3')
00405EC6  |. |8B55 C4       ||MOV EDX,DWORD PTR SS:[EBP-3C]
00405EC9  |. |83C2 01       ||ADD EDX,1
00405ECC  |. |8955 C4       ||MOV DWORD PTR SS:[EBP-3C],EDX
00405ECF  |> |EB 0F         ||JMP SHORT 1.00405EE0
00405ED1  |> |8B85 1CFEFFFF ||MOV EAX,DWORD PTR SS:[EBP-1E4]
00405ED7  |. |83C0 01       ||ADD EAX,1
00405EDA  |. |8985 1CFEFFFF ||MOV DWORD PTR SS:[EBP-1E4],EAX
00405EE0  |> |EB 1E         ||JMP SHORT 1.00405F00
00405EE2  |> |8B4D E0       ||MOV ECX,DWORD PTR SS:[EBP-20]
00405EE5  |. |83E9 01       ||SUB ECX,1
00405EE8  |. |894D E0       ||MOV DWORD PTR SS:[EBP-20],ECX
00405EEB  |. |8B55 08       ||MOV EDX,DWORD PTR SS:[EBP+8]
00405EEE  |. |52            ||PUSH EDX                               ; /Arg2
00405EEF  |. |8B85 28FEFFFF ||MOV EAX,DWORD PTR SS:[EBP-1D8]         ; |
00405EF5  |. |50            ||PUSH EAX                               ; |Arg1
00405EF6  |. |E8 F50C0000   ||CALL 1.00406BF0                        ; \1.00406BF0
00405EFB  |. |83C4 08       ||ADD ESP,8
00405EFE  |. |EB 05         ||JMP SHORT 1.00405F05
00405F00  |>^\E9 B9FEFFFF   |\JMP 1.00405DBE



0x00405de8处的call是从文件中读取一个字节放到eax中,

0x00405df6判断是否读到文件结束,

从00405E03  到00405E2B 的代码致使这个问题的出现,解释下这段
EBP-1D8中存放从文件中读取的一个字节,然后右移3位,这里不难分析ecx的取值范围0~1f,

往下405e0c处代码,分析这一句ebp+ecx-60的范围应该在ebp-41到ebp-60,看下内存:


选中部分有两处值不为0,而当EBP-1D8中的值为0x0a或者0x0d这样时则ebp+ecx-60命中0x3e,
0x00405E11处代码ebp-10取值始终为0xff。将ebp+ecx-60 与ebp-10的值xor存于edx,再将读取的一个字节与7进行and存放在ecx,(讲的可能有点乱,还5行直接贴代码吧)
00405E1D  |.  83E1 07       ||AND ECX,7                              ;  3
00405E20  |.  B8 01000000   ||MOV EAX,1
00405E25  |.  D3E0          ||SHL EAX,CL                             ;  8
00405E27  |.  23D0          ||AND EDX,EAX                            ;  8
00405E29  |.  85D2          ||TEST EDX,EDX
00405E2B  |.  0F84 B1000000 ||JE 1.00405EE2



当读入字节为0x0a时,0x00405E2b处跳转实现,和上面判断为文件结束跳向同一地址。。

如果我们有需要fscanf 0x0a这样的字节岂不是scanf不进去了?

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 0
支持
分享
最新回复 (4)
雪    币: 261
活跃值: (51)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
fscanf不就是按照white space分隔输入的么?既然是一次读取就用fread呀
另外非文本文件要用二进制的方法打开,不然在windows下读到换行会有问题
2015-2-2 08:05
0
雪    币: 9
活跃值: (394)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
不细心呵呵
2015-2-2 09:33
0
雪    币: 19
活跃值: (74)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
0x0a \n
0x0d \r
2015-2-2 12:39
0
雪    币: 65
活跃值: (27)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
5
是的是的,惭愧了。感谢楼上各位的回答。我换个方式去读:)
2015-2-2 15:21
0
游客
登录 | 注册 方可回帖
返回
//