如何在MASM32中打印结构体所有字段及转储打印其内存字节?
问题解答:MASM32中打印PE结构体与内存字节转储
一、一次性打印IMAGE_DOS_HEADER所有字段
MASM32没有原生的结构体反射机制,需手动遍历每个字段,结合类型转换函数逐个打印。以下是具体实现:
首先确保正确定义IMAGE_DOS_HEADER结构体:
IMAGE_DOS_HEADER STRUCT e_magic WORD ? ; MZ标志 e_cblp WORD ? e_cp WORD ? e_crlc WORD ? e_cparhdr WORD ? e_minalloc WORD ? e_maxalloc WORD ? e_ss WORD ? e_sp WORD ? e_csum WORD ? e_ip WORD ? e_cs WORD ? e_lfarlc WORD ? e_ovno WORD ? e_res WORD 4 DUP (?) e_oemid WORD ? e_oeminfo WORD ? e_res2 WORD 10 DUP (?) e_lfanew DWORD ? ; PE头偏移 IMAGE_DOS_HEADER ENDS
编写处理不同类型字段的打印辅助函数:
; 打印WORD类型字段 ; 参数:字段名字符串偏移、字段值 PrintWordField proc uses ebx edx, fieldName:DWORD, value:WORD pushad print fieldName, 0 print ": ", 0 movzx eax, value invoke dw2hex, eax, addr buffer print offset buffer, 0Dh, 0Ah, 0 popad ret PrintWordField endp ; 打印DWORD类型字段 ; 参数:字段名字符串偏移、字段值 PrintDwordField proc uses ebx edx, fieldName:DWORD, value:DWORD pushad print fieldName, 0 print ": ", 0 invoke dw2hex, value, addr buffer print offset buffer, 0Dh, 0Ah, 0 popad ret PrintDwordField endp
在主逻辑中调用函数打印所有字段:
; 假设dosHeader是已填充的结构体实例 invoke PrintWordField, offset szEMagic, dosHeader.e_magic invoke PrintWordField, offset szECblp, dosHeader.e_cblp invoke PrintWordField, offset szECp, dosHeader.e_cp invoke PrintWordField, offset szECrlc, dosHeader.e_crlc invoke PrintWordField, offset szECparhdr, dosHeader.e_cparhdr invoke PrintWordField, offset szEMinalloc, dosHeader.e_minalloc invoke PrintWordField, offset szEMaxalloc, dosHeader.e_maxalloc invoke PrintWordField, offset szESs, dosHeader.e_ss invoke PrintWordField, offset szESp, dosHeader.e_sp invoke PrintWordField, offset szECsum, dosHeader.e_csum invoke PrintWordField, offset szEIp, dosHeader.e_ip invoke PrintWordField, offset szECs, dosHeader.e_cs invoke PrintWordField, offset szELfarlc, dosHeader.e_lfarlc invoke PrintWordField, offset szEOvno, dosHeader.e_ovno ; 打印e_res数组(4个WORD) mov ecx, 4 mov ebx, offset dosHeader.e_res print offset szERes, 0, ": ", 0 ResLoop: movzx eax, WORD ptr [ebx] invoke dw2hex, eax, addr buffer print offset buffer, 0 add ebx, 2 dec ecx jnz ResLoop print 0Dh, 0Ah, 0 invoke PrintWordField, offset szEOemid, dosHeader.e_oemid invoke PrintWordField, offset szEOeminfo, dosHeader.e_oeminfo ; 打印e_res2数组(10个WORD) mov ecx, 10 mov ebx, offset dosHeader.e_res2 print offset szERes2, 0, ": ", 0 Res2Loop: movzx eax, WORD ptr [ebx] invoke dw2hex, eax, addr buffer print offset buffer, 0 add ebx, 2 dec ecx jnz Res2Loop print 0Dh, 0Ah, 0 invoke PrintDwordField, offset szELfanew, dosHeader.e_lfanew ; 字段名字符串定义 szEMagic db "e_magic", 0 szECblp db "e_cblp", 0 szECp db "e_cp", 0 szECrlc db "e_crlc", 0 szECparhdr db "e_cparhdr", 0 szEMinalloc db "e_minalloc", 0 szEMaxalloc db "e_maxalloc", 0 szESs db "e_ss", 0 szESp db "e_sp", 0 szECsum db "e_csum", 0 szEIp db "e_ip", 0 szECs db "e_cs", 0 szELfarlc db "e_lfarlc", 0 szEOvno db "e_ovno", 0 szERes db "e_res", 0 szEOemid db "e_oemid", 0 szEOeminfo db "e_oeminfo", 0 szERes2 db "e_res2", 0 szELfanew db "e_lfanew", 0 buffer db 16 dup(0)
二、转储并打印结构体的内存字节
实现示例格式的内存转储,需循环读取每个字节,格式化地址和十六进制值,每行显示16个字节:
; 内存转储打印函数 ; 参数:起始地址、内存长度 DumpMemory proc uses ebx ecx edx esi edi, startAddr:DWORD, length:DWORD pushad mov esi, startAddr mov ecx, length DumpLoop: ; 打印当前地址(0xXXXXXXXX格式) mov eax, esi print "0x", 0 invoke dw2hex, eax, addr buffer print offset buffer, 0, " ", 0 ; 打印16个字节的十六进制 mov ebx, 16 ByteLoop: cmp ecx, 0 jz EndByteLoop mov al, byte ptr [esi] invoke byte2hex, al, addr buffer print offset buffer, 0, " ", 0 inc esi dec ecx dec ebx jnz ByteLoop EndByteLoop: print 0Dh, 0Ah, 0 cmp ecx, 0 jnz DumpLoop popad ret DumpMemory endp ; 字节转十六进制辅助函数 byte2hex proc uses ebx, b:BYTE pushad mov al, b mov bl, al shr al, 4 call HexChar mov buffer[0], al mov al, bl and al, 0Fh call HexChar mov buffer[1], al mov buffer[2], 0 popad ret HexChar: cmp al, 0Ah jl IsDigit add al, 37h ret IsDigit: add al, 30h ret byte2hex endp
调用方式(打印整个IMAGE_DOS_HEADER结构体):
invoke DumpMemory, offset dosHeader, sizeof IMAGE_DOS_HEADER
内容的提问来源于stack exchange,提问作者HappyLuck99
相关产品推荐
相关产品推荐

