汇编调用Windows API复制文件丢失首词问题求助
汇编复制TXT文件丢失首个单词的Bug排查与修复
问题描述
使用Windows API编写汇编代码复制TXT文件,复制后原文件首个单词丢失。输入示例:
- 源文件路径:
C:\Users\User\Desktop\qwe\qwe.txt - 目标文件路径:
C:\Users\User\Desktop\qwe2\qwe2.txt
原始代码
%include "io.inc" extern _access extern _MessageBoxA@16 extern _CloseHandle@4 extern _CreateFileA@28 extern _WriteFile@20 extern _ReadFile@20 extern _strcat extern _strlen extern _strtok section .data buffer1 times 0xff db 0x0 buffer1_len equ $ - buffer1 buffer2 times 0xff db 0x0 buffer2_len equ $ - buffer2 caption db 'Do you want to Copy?', 0x0 format db 0x0a, 0x00 error db 'There is no file', 0x0d, 0x00 error_caption db 'error', 0x0d, 0x00 file db 0x00 file2 db 0x00 read_file_pointer times 0xffff dq 0x00 new_file db 0x00 read_len times 0xfffff dq 0x00 section .text global CMAIN filecheck: push 0x00 push buffer1 call _access add esp, 8 cmp eax, 0 jne error_message call copy ret copy: push ebp mov ebp, esp push 0x0 push 0x0 push 0x3 push 0x0 push 0x0 push 0x1 push buffer1 call _CreateFileA@28 mov [file], eax push 0x0 push read_len push 0xff push read_file_pointer push dword [file] call _ReadFile@20 push dword [file] call _CloseHandle@4 push 0 push 0x80 push 2 push 0 push 0 push 0x40000000 push buffer2 call _CreateFileA@28 mov [file2], eax ;Write File push 0 push 0 push dword [read_len] push read_file_pointer push dword [file2] call _WriteFile@20 push dword [file2] call _CloseHandle@4 mov esp, ebp pop ebp ret error_message: push dword 0x0 push dword error_caption push dword error push dword 0x0 call _MessageBoxA@16 cmp eax, 1 je program_exit message_box: push dword 0x4 push dword caption push dword buffer1 push dword 0x0 call _MessageBoxA@16 ret cat: push ebp mov ebp, esp push buffer2 push buffer1 call _strcat mov esp, ebp pop ebp ret strlens: push ebp mov ebp, esp push format push buffer1 call _strtok mov esp, ebp pop ebp ret CMAIN: mov ebp, esp; for correct debugging mov ax, buffer1_len GET_STRING buffer1, ax mov ax, buffer2_len GET_STRING buffer2, ax call cat call message_box call strlens call filecheck program_exit: xor eax, eax ret
问题根源分析
冗余字符串操作破坏源路径:
cat函数调用_strcat(buffer1, buffer2),将目标路径拼接到源路径缓冲区末尾,直接破坏了buffer1中存储的源文件路径,导致后续CreateFileA打开的不是正确的源文件。strlens函数调用_strtok(buffer1, format),进一步修改buffer1的内容,截断路径字符串,加剧了路径错误问题。这两个函数完全多余,复制文件不需要此类操作。
变量类型不匹配:
file和file2定义为单字节db 0x00,但Windows API的CreateFileA返回的HANDLE在32位系统中是4字节DWORD,存储时会截断句柄值,导致后续ReadFile/WriteFile/CloseHandle使用无效句柄。
缓冲区与长度变量定义冗余:
read_len定义为超大数组times 0xfffff dq 0x00,但ReadFile只需要一个指向DWORD的指针接收实际读取字节数,冗余定义会导致内存浪费且可能引发指针错误。read_file_pointer定义为times 0xffff dq 0x00,实际每次仅读取0xff字节,无需如此大的空间。
修复后的代码
%include "io.inc" extern _access extern _MessageBoxA@16 extern _CloseHandle@4 extern _CreateFileA@28 extern _WriteFile@20 extern _ReadFile@20 section .data buffer1 times 0xff db 0x0 buffer1_len equ $ - buffer1 buffer2 times 0xff db 0x0 buffer2_len equ $ - buffer2 caption db 'Do you want to Copy?', 0x0 error db 'There is no file', 0x0d, 0x00 error_caption db 'error', 0x0d, 0x00 ; 修复:HANDLE是32位DWORD,用dd定义 file dd 0x00 file2 dd 0x00 ; 修复:读取缓冲区只需0xff字节,匹配ReadFile的读取长度 read_buffer times 0xff db 0x0 ; 修复:read_len用DWORD变量存储实际读取字节数 read_len dd 0x00 section .text global CMAIN filecheck: push 0x00 push buffer1 call _access add esp, 8 cmp eax, 0 jne error_message call copy ret copy: push ebp mov ebp, esp ; 打开源文件:GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING push 0x0 push 0x0 push 0x3 push 0x0 push 0x0 push 0x80000000 ; GENERIC_READ push buffer1 call _CreateFileA@28 mov [file], eax ; 读取文件内容到read_buffer push 0x0 push read_len push 0xff push read_buffer push dword [file] call _ReadFile@20 push dword [file] call _CloseHandle@4 ; 打开目标文件:GENERIC_WRITE, CREATE_ALWAYS push 0 push 0x80 push 2 push 0 push 0 push 0x40000000 ; GENERIC_WRITE push buffer2 call _CreateFileA@28 mov [file2], eax ; 写入文件内容 push 0 push 0 push dword [read_len] push read_buffer push dword [file2] call _WriteFile@20 push dword [file2] call _CloseHandle@4 mov esp, ebp pop ebp ret error_message: push dword 0x0 push dword error_caption push dword error push dword 0x0 call _MessageBoxA@16 cmp eax, 1 je program_exit message_box: push dword 0x4 push dword caption push dword buffer1 push dword 0x0 call _MessageBoxA@16 ret CMAIN: mov ebp, esp; for correct debugging mov ax, buffer1_len GET_STRING buffer1, ax mov ax, buffer2_len GET_STRING buffer2, ax call message_box call filecheck program_exit: xor eax, eax ret
修复说明
- 移除冗余函数:删除
cat和strlens函数,避免破坏源路径缓冲区buffer1。 - 修正变量类型:将
file和file2改为dd 0,正确存储32位文件句柄。 - 优化缓冲区与长度变量:
- 将
read_file_pointer改为read_buffer,大小设为0xff字节,匹配每次读取的长度。 - 将
read_len改为dd 0,作为ReadFile接收实际读取字节数的变量。
- 将
- 修正CreateFileA的访问权限:打开源文件时使用
0x80000000(GENERIC_READ),确保正确的读取权限。
内容的提问来源于stack exchange,提问作者Persshins
相关产品推荐
相关产品推荐

