neuviemeporte / mzretools

Tools for reversing DOS games, primarily inspection of MZ executables
GNU General Public License v2.0
33 stars 2 forks source link

Exception: Incorrect read size from MzImage file: 15 #5

Open pppq opened 2 months ago

pppq commented 2 months ago

Hello, just wanted to add my +1 for this comment 😸 https://github.com/neuviemeporte/mzretools/blob/7b9553fa11f01dcdf9c04e7d601662b69b38cb13/src/mz.cpp#L42-L44

Changing r to rb fixes my issue which was encountering a 0x1A (Ctrl-Z) character early in the MZ header; this was interpreted as an EOF character in Windows resulting in the message above. I built mzhdr in MSYS2's MINGW64 environment (x86_64-w64-mingw32). I don't know if opening the file in binary mode breaks any other expectation elsewhere.

neuviemeporte commented 2 months ago

@pppq: Thanks for the info, would you be able to send or link to an example exe file with this problem? That way, I could have a unit test covering this scenario. I guess the header payload should be enough...

pppq commented 2 months ago

I tried to create a small reproducer using a small modification of a "Hello world" example which I found at https://github.com/britovski/tasm_hello

--- HELLO_ORIG.ASM
+++ HELLO.ASM
@@ -1,5 +1,5 @@
     .MODEL small
-    .STACK 100h
+    .STACK 11ah
     .DATA
 HelloMessage DB 'Hello, world',13,1,''
     .CODE

The error message did show up, but unfortunately the built .EXE did not work (this might have to do more with my build environment though). Here is the header dumped when I change the mode parameter of fopen to rb:

--- HELLO.EXE MZ header (28 bytes)
        [0x0] signature = 0x5a4d ('MZ')
        [0x2] last_page_size = 0x3e (62 bytes)
        [0x4] pages_in_file = 2 (1024 bytes, load module = 62/0x3e bytes)
        [0x6] num_relocs = 2
        [0x8] header_paragraphs = 32 (512 bytes)
        [0xa] min_extra_paragraphs = 18 (288 bytes)
        [0xc] max_extra_paragraphs = 65535
        [0xe] ss:sp = 4:11a --> reflects modified .STACK directive
        [0x12] checksum = 0x0
        [0x16] cs:ip = 0:0
        [0x18] reloc_table_offset = 0x3e
        [0x1a] overlay_number = 0
--- extra data (overlay info?)
        0x01, 0x00, 0xfb, 0x50, 0x6a, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
--- relocations:
        [0]: 0:1, linear: 0x1, file offset: 0x201, file value = 0x3
        [1]: 0:18, linear: 0x18, file offset: 0x218, file value = 0x3
--- load module @ 0x200, size = 0x3e / 62 bytes

The unmodified mzhdr can read the .EXE built from the unmodified .ASM (when SP is initialized to 0x100) but breaks with "Exception: Incorrect read size from MzImage file: 16" if I try to parse the header of the executable built from the modified source file.