Solved

Program that is 'not a valid win32 application'

Posted on 2000-04-24
30
609 Views
Last Modified: 2013-12-03
I have written a program 'wrapper' that appends itself to an existing program. This works, (and has worked for 12 months or more) on W95 and W98 but now I have to convert it to work on NT and W2000.

When I try to run the program however windows reports 'program xxx.exe is not a valid win32 application' and the program does not even begin to run.

What could be causing this problem? I suspect it could be something in the PE header but I don't know for sure and I don't know how to find out what W2000 is complaining about.

If need be I can email the program (it is about 250k zipped) to anyone who is prepared to look at this problem.

The high points are because I have spent a lot of time on this and been unable to fix it and anyone able to help is likely to need to have good knowledge of PE file formats and W2000.

0
Comment
Question by:styx
  • 10
  • 7
  • 4
  • +6
30 Comments
 
LVL 1

Expert Comment

by:Rheingold
ID: 2744525
Hi

can I have a look at the prog? - lazarus@hello.to
0
 

Author Comment

by:styx
ID: 2744602
Here is a dump of the headers of the file if anyone can see anything 'wrong' with it (it works OK on W95,W98 but not on W2000).

Microsoft (R) COFF Binary File Dumper Version 5.00.7022
Copyright (C) Microsoft Corp 1992-1997. All rights reserved.


Dump of file CALC.EXE

PE signature found

File Type: EXECUTABLE IMAGE

FILE HEADER VALUES
     14C machine (i386)
       6 number of sections
37ECAB3B time date stamp Sat Sep 25 12:00:11 1999
       0 file pointer to symbol table
       0 number of symbols
      E0 size of optional header
     30F characteristics
            Relocations stripped
            Executable
            Line numbers stripped
            Symbols stripped
            32 bit word machine
            Debug information stripped

OPTIONAL HEADER VALUES
     10B magic #
    5.12 linker version
   5F600 size of code
    DE00 size of initialized data
       0 size of uninitialized data
   29470 address of entry point
    1000 base of code
   14000 base of data
         ----- new -----
 1000000 image base
    1000 section alignment
     200 file alignment
       2 subsystem (Windows GUI)
    5.00 operating system version
    5.00 image version
    4.00 subsystem version
   76000 size of image
     600 size of headers
   1BA59 checksum
  100000 size of stack reserve
    1000 size of stack commit
  100000 size of heap reserve
    1000 size of heap commit
    8000 dll characteristics
            RESERVED - UNKNOWN
       0 [       0] address [size] of Export Directory
   70000 [      64] address [size] of Import Directory
   16000 [    2B98] address [size] of Resource Directory
       0 [       0] address [size] of Exception Directory
       0 [       0] address [size] of Security Directory
       0 [       0] address [size] of Base Relocation Directory
       0 [       0] address [size] of Debug Directory
       0 [       0] address [size] of Description Directory
       0 [       0] address [size] of Special Directory
       0 [       0] address [size] of Thread Storage Directory
       0 [       0] address [size] of Load Configuration Directory
     238 [      80] address [size] of Bound Import Directory
   701D4 [     170] address [size] of Import Address Table Directory
       0 [       0] address [size] of Reserved Directory
       0 [       0] address [size] of Reserved Directory
       0 [       0] address [size] of Reserved Directory


SECTION HEADER #1
   .text name
   124EE virtual size
    1000 virtual address
   12600 size of raw data
     600 file pointer to raw data
       0 file pointer to relocation table
       0 file pointer to line numbers
       0 number of relocations
       0 number of line numbers
E0000020 flags
         Code
         (no align specified)
         Execute Read Write

SECTION HEADER #2
   .data name
    10C0 virtual size
   14000 virtual address
     C00 size of raw data
   12C00 file pointer to raw data
       0 file pointer to relocation table
       0 file pointer to line numbers
       0 number of relocations
       0 number of line numbers
C0000040 flags
         Initialized Data
         (no align specified)
         Read Write

SECTION HEADER #3
   .rsrc name
    3000 virtual size
   16000 virtual address
    3000 size of raw data
   13800 file pointer to raw data
       0 file pointer to relocation table
       0 file pointer to line numbers
       0 number of relocations
       0 number of line numbers
C0000040 flags
         Initialized Data
         (no align specified)
         Read Write

SECTION HEADER #4
    icd1 name
   56000 virtual size
   1A000 virtual address
   52C00 size of raw data
   16800 file pointer to raw data
       0 file pointer to relocation table
       0 file pointer to line numbers
       0 number of relocations
       0 number of line numbers
E0000060 flags
         Code
         Initialized Data
         (no align specified)
         Execute Read Write

SECTION HEADER #5
  .idata name
     A00 virtual size
   70000 virtual address
     A00 size of raw data
   69400 file pointer to raw data
       0 file pointer to relocation table
       0 file pointer to line numbers
       0 number of relocations
       0 number of line numbers
C0000040 flags
         Initialized Data
         (no align specified)
         Read Write

SECTION HEADER #6
    icd2 name
    41F0 virtual size
   71000 virtual address
    4200 size of raw data
   69E00 file pointer to raw data
       0 file pointer to relocation table
       0 file pointer to line numbers
       0 number of relocations
       0 number of line numbers
C0000040 flags
         Initialized Data
         (no align specified)
         Read Write

     Summary

        2000 .data
        1000 .idata
        3000 .rsrc
       13000 .text
       56000 icd1
        5000 icd2
0
 
LVL 86

Expert Comment

by:jkr
ID: 2745149
The *header* sems OK, but what about the rest of the file? This error mostly occurs when there's been a problem with copying the file - try to copy it to your machine again...
0
 
LVL 3

Expert Comment

by:luisr
ID: 2745164
The PE header has a Checksum field with is supposed to have something like a CRC of the executable, but it was not used before. Windows 2000 now requires executables to have the correct checksum or else it won't run them.

Since your modifying an executable by appending another to it, you must recalculate the checksum for it to run under Win2k.

Matt Pietrek's excellent "Windows 95 System Programming Secrets" says that the checksum algorithm is provided by IMAGEHLP.DLL, so you may find additional info in its docs.
0
 
LVL 23

Expert Comment

by:chensu
ID: 2745386
I think luisr is on the right track. You probably need to use MapFileAndCheckSum or CheckSumMappedFile.
0
 

Author Comment

by:styx
ID: 2745459
luisr

Thanks, I will look into that suggestion. I hope that it is what is causing the problem since it should be relatively easy to fix!

It may be a few days before I can try this out so don't be too upset if I don't get back right away!

0
 

Author Comment

by:styx
ID: 2745476
luisr

It it is indeed the case that it is the checksum then 'patching' an exe file (by changing some of the bytes) should generate the same error. When I try this on the windows calculator (or at least a copy of it!) then I can't cause the problem.

Will get back later.
0
 
LVL 15

Expert Comment

by:NickRepin
ID: 2745479
Just try to set the Checksum field in the PE header to zero to make sure that the problem is there.
0
 

Author Comment

by:styx
ID: 2745504
I have changed the checksum in the windows calculator to various values, and it still works OK.

I have changed the checksum in the 'wrapped' windows calculator to various values (including zero) and it still fails.

I suspect that this is not the solution unless there is something else that needs changing as well. How for example would W2000 cope with programs built for W95 and W98 which either did not use the checksum field or set it to incorrect values?
0
 
LVL 15

Expert Comment

by:NickRepin
ID: 2745529
You definitely have to put your file on ftp or something so that we can test it.
Could you can send it to nick@earthspeak.net ?
0
 
LVL 3

Expert Comment

by:luisr
ID: 2745809
If I can remember well, the PE header also contains some fields about minium required operating system version (I remember having to set the subsystem version to 4.0 for apps to use new Win95 features). I don't know, but it may be that Win2K checks that version, and if the EXE is targeted for Win9x, then forgets all that checksum checks.

I once wrote a little utility to increment the build number of an executable, and it modified directly the version resource after the EXE was linked. It worked all right on 9x, but I received reports that EXEs on which it was applied failed to run on Win2K.
0
 
LVL 3

Expert Comment

by:luisr
ID: 2745839
styx, can you please explain how your program works?? It could save the original program as a resource or append at the end of the original program and modify the header, or... how does it work?
0
 

Author Comment

by:styx
ID: 2746320
luisr.

The original program (in my current example the windows calculator) is encrypted. The wrapper is then appended at the end of the existing program by adding a few new sections.

Various parts of the PE header are modified accordingly and the program entry point is modified to point to the new code.

When the program runs it decrypts the original program and jumps to the original entry point.

As I said above, this works OK on W95 and W98, not on W2000 (and I presume NT although I am not in a position to try it just yet).

Styx
0
 

Author Comment

by:styx
ID: 2746325
NickRepin.

A copy of the program has been sent to you.

Does anyone else want to be sent a copy?

Styx
0
 
LVL 3

Expert Comment

by:luisr
ID: 2746359
Does it decrypt the original program in memory? if so, Windows may load some part of the code, run it, and later try to reload some other part, and fail when it finds invalid code.

Unfortunately I have yet to install Win2K, so I cannot test your program.
0
6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

 
LVL 20

Expert Comment

by:Madshi
ID: 2746538
listening...
0
 
LVL 14

Expert Comment

by:AlexVirochovsky
ID: 2747136
To all experts: are you sure, that
styx's app isn't virus? By description, i guess, that it is virus!
0
 
LVL 20

Expert Comment

by:Madshi
ID: 2747159
If it would be virus, why should he encrypt the original program? No, I don't think so...
0
 
LVL 1

Expert Comment

by:Rheingold
ID: 2747198
I don't think that it is a virus either. (It has several features that differ it from virii) I was messing with the PE header until 3 in the morning, but I can't get the reason, yet. Well... I keep on trying.
0
 
LVL 4

Expert Comment

by:Radler
ID: 2747553
listening...
0
 

Author Comment

by:styx
ID: 2747964
AlexVirochovsky

Not it is not a virus (but you are right to ask the question) although the description I gave could be taken to describe a virus.

The program is part of a security system I have devised to protect programs from being reverse engineered. In another context it prevents copies of the program from being run. Hence the encryption of the original program.

I have been doing searches on the web for similar error message but most of the references I have found refer to programs that have been corrupted in some way when downloaded.

One approach I may have to take is to use SoftIce to break on the error message and try to reverse engineer windows to see what it is objecting about. I don't however have a version of SoftIce which works on W2000 so I suppose that is another expense!

Styx
0
 
LVL 1

Expert Comment

by:Rheingold
ID: 2749143
Hi

I don't know if it's of too much use, but I went through another prog (which runs on Win2K) and changed several stuff using a HexEditor to find out what causes this kind of message. Here are my findings (just that nobody does the same work).

I went through all values and set them to 0, FFFFFFFF and 1 or 2 values in between to find out.
I don't know how reliable this data is, but maybe you can use it.

Dos stub: Doesn't matter except the MZ and the word where the PE section begins
000 pe signiture            Causes problems but does not seem to be the reason
004 MACHINE                 Doesn't cause problems
006 NumberOfSections        Causes problems but does not seem to be the reason
008 TimeDateStamp           Doesn't cause problems
00c PointerToSymbolTable    Doesn't cause problems
010 NumberOfSymbols         Doesn't cause problems
014 SizeOfOptionalHeader    Causes problems but does not seem to be the reason
016 Characteristics         Causes problems - seems OK, but I am not sure
018 Magic                   Causes problems but does not seem to be the reason
01a MajorLinkerVersion      Doesn't cause problems
01b MinorLinkerVersion      Doesn't cause problems
01c SizeOfCode              Doesn't cause problems
020 SizeOfInitializedData   Doesn't cause problems
024 SizeOfUninitializedData Doesn't cause problems
028 AddressOfEntryPoint     Doesn't cause problems (nevertheless in which section it
                                                    lies and how those sect. character. are)
02c BaseOfCode              Doesn't cause problems
030 BaseOfData              Doesn't cause problems
034 ImageBase               Crashes, but doesn't show "Invalid EXE" message - maybe relocations problem
038 SectionAlignment        Causes problems but does not seem to be the reason
03c FileAlignment           Causes problems but does not seem to be the reason
040 MajorOperatingSystemVersion Doesn't cause problems
042 MinorOperatingSystemVersion Doesn't cause problems
044 MajorImageVersion       Doesn't cause problems
046 MinorImageVersion       Doesn't cause problems
048 MajorSubsystemVersion   Causes problems (04 and 05 are valid -> not the reason)
04a MinorSubsystemVersion   Doesn't cause problems
04c Reserved1               Doesn't cause problems
050 SizeOfImage             Causes problems and is maybe the reason
    SizeOfImage is the sum of all space the sections need when they are aligned to
    "SectionAlignment". Correct me if I'm wrong:
    We have those sections:
    Name    Size     Aligned Size
    .TEXT   124EE    13000
    .DATA   010C0    02000
    .RSRC   03000    03000
    ICD1    56000    56000
    .IDATA  00A00    01000
    ICD2    041F0    05000
    ----------------------
                     74000

   The sum of all of them is 74000, but the PE header says 76000.
   I changed the value to 74000, but it still crashes. Either I calculated wrong or there
   are more reasons.
054 SizeOfHeaders           Can cause problems but does not seem to be the reason (600 is correct)
058 CheckSum                Checksum is set to 0, so it doesn't cause probs
05c Subsystem               Can cause problems, but displays another messagebox (02 is GUI anyway)
05e DllCharacteristics      Doesn't cause problems
060 SizeOfStackReserve      Can cause problems another message, though
064 SizeOfStackCommit       Can cause problems another message, though
068 SizeOfHeapReserve       Can cause problems another message, though
06c SizeOfHeapCommit        Can cause problems another message, though
070 LoaderFlags             Doesn't cause problems
074 NumberOfRvaAndSizes     Can cause problems but without error message
078 IMAGE_DIRECTORY_ENTRY_EXPORT    Doesn't cause problems
080 IMAGE_DIRECTORY_ENTRY_IMPORT    Can cause problems but with other or no messages
088 IMAGE_DIRECTORY_ENTRY_RESOURCE  Can cause problems but with other or no messages
090 IMAGE_DIRECTORY_ENTRY_EXCEPTION Doesn't cause problems
098 IMAGE_DIRECTORY_ENTRY_SECURITY  Doesn't cause problems
0a0 IMAGE_DIRECTORY_ENTRY_BASERELOC Doesn't cause problems
0a8 IMAGE_DIRECTORY_ENTRY_DEBUG     Doesn't cause problems
0b0 IMAGE_DIRECTORY_ENTRY_COPYRIGHT Doesn't cause problems
0b8 IMAGE_DIRECTORY_ENTRY_GLOBALPTR Doesn't cause problems
0c0 IMAGE_DIRECTORY_ENTRY_TLS       Can cause problems but with another message
0c8 IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG Causes problems (My PE doc says "Purpose and Structure
                                      unknow, but at least my prog works with the value 0 and
                                      your prog has that)
0d0 IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT Doesn't cause problems
0d8 IMAGE_DIRECTORY_ENTRY_IAT          Can cause problems but with another message
The rest doesn't cause problems either

I was not able to cause this problem by changing the section characteristics. Either it crashes, doesn't run or runs normal.

Oh boy, this will be very unstructered, I fear...

Regards
0
 
LVL 15

Accepted Solution

by:
NickRepin earned 1000 total points
ID: 2749904
You have incorrectly calculated the RVA of the 4th object icd1

Currently:

Object table:
#   Name      VirtSize    RVA     PhysSize  Phys off  Flags  
--  --------  --------  --------  --------  --------  --------
01  .text     000124EE  00001000  00012600  00000600  E0000020 [CERW]
02  .data     000010C0  00014000  00000C00  00012C00  C0000040 [IRW]
03  .rsrc     00003000  00016000  00003000  00013800  C0000040 [IRW]
04  icd1      00056000  0001A000  00052C00  00016800  E0000060 [CEIRW]
05  .idata    00000A00  00070000  00000A00  00069400  C0000040 [IRW]
06  icd2      000041F0  00071000  00004200  00069E00  C0000040 [IRW]

Must be:
(16000+3000)=19000, not 1A000

#   Name      VirtSize    RVA     PhysSize  Phys off  Flags  
--  --------  --------  --------  --------  --------  --------
01  .text     000124EE  00001000  00012600  00000600  E0000020 [CERW]
02  .data     000010C0  00014000  00000C00  00012C00  C0000040 [IRW]
03  .rsrc     00003000  00016000  00003000  00013800  C0000040 [IRW]
04  icd1      00056000  00019000  00052C00  00016800  E0000060 [CEIRW]
05  .idata    00000A00  0006F000  00000A00  00069400  C0000040 [IRW]
06  icd2      000041F0  00070000  00004200  00069E00  C0000040 [IRW]


Respectively, you have to change the image size to 75000.

Now the image loads fine, but still not work because you have to recalculate some other data - imports, etc.
I'll try to do this in some hours.

0
 
LVL 15

Expert Comment

by:NickRepin
ID: 2750024
It would be much easy:

1) Change the virtual size of the .rsrc object from 3000 to 4000 to eliminate the need for changing all other data.

3000 virtual size
to
4000 virtual size
   

2) Remove bound import directory (place zero both in RVA and size)

238 [      80] address [size] of Bound Import Directory
to
0 [      0] address [size] of Bound Import Directory

Now your program will successfully start on NT4/2000 and run your entry point.

I hope I answered to your question.
I have not checked whether your programs successfully unpacks and runs the original calc.exe or not - it's not my business, at least it is not related to the question.

I ran the program on NT4 - it began to access CDROM, floppies and I cancelled it. I hope it doesn't contain anything that could damage my NT ;)
0
 

Author Comment

by:styx
ID: 2750394
NickRepin.

That sounds very promising. I cannot look into this in any detail today but I have time tomorrow (Thursday) to check it out and hopefully award you the points!

Styx
0
 
LVL 15

Expert Comment

by:NickRepin
ID: 2751026
Probably, I have to clarify my answer regarding the bound import table.

I should say that I have no the exact description of the purpose of that table.

But definitely it is required by the NT loader to properly resolve the external references of the calc.exe during the load.

Since you replaced the original calc.exe code with your own sections, the original bound import table became invalid. That's why you have to remove it from the final exe image. Of course, you have to restore it (or at least emulate its functionality) when you unpacked the original calc.exe code.
0
 

Author Comment

by:styx
ID: 2754602
NickRepin

I manually changed the virtual size of the .rsrc section as you suggested an zeroed out the bound import directory and the program then ran (but crashed). It should now just come down to debugging which is relatively easy!

As an experiement I zeroed out the bound import directory of the original calc.exe and the program ran OK. I have not found any reference to this field to find out what it is used for. I assume it is to do with binding a DLL import to a set memory address to reduce the time it takes to resolve and fix-up some DLL calls. If this is the case then zeroing it out should not have any effect other than a marginal increase in the time to load.

It is interesting that having gaps in the virtual address space works OK on W95 and W98 but not on NT. Now I know I can adjust my program accordingly.

Thanks for all your help. It was invaluable (and certainly worth the 1000 points).

Styx
0
 
LVL 15

Expert Comment

by:NickRepin
ID: 2754873
Thanks for points.
I've increased my PE knowledge too.

Have a look at BindImageEx and BindImage, it seems they modify the bound import directory. Mey be, you'll find something useful for you.

Regards, Nick.
0
 

Author Comment

by:styx
ID: 2758356
I don't expect you to answer this, it is just an observation of mine and something that I may have to look into further.

The main problem seemed to be the virtual size of the .rsrc section added to the RVA of that section did not equal the start of the next section. (16000 + 3000 = 19000 and not 1A000). Now how is this different to the size and RVA of the first .text section (124EE + 1000 = 134EE and not 14000). I can only think that these values are rounded up by the Windows loader to the next 1000 address. In the non-working case of the .rsrc section the difference was 1000 or more wheras in all other working cases the difference is always less than 1000.

BTW. The 'bug' in the program was that when I appended the wrapper onto the original program I had not taken into account the fact that the first section of the wrapper was at RVA of 1000, hence the 1000 byte gap between sections.

Thanks again for your help.


0
 
LVL 15

Expert Comment

by:NickRepin
ID: 2758637
The header says that the section alignment is 1000, the file alignment is 200.
That's why the physical (raw) sizes are rounded to 200, and the virtual sizes (ie mapped into memory) are rounded to 1000.

So you could specify the .rsrc virtual size as 3001 (not 4000). It will be rounded to 4000.
0

Featured Post

Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

Join & Write a Comment

Suggested Solutions

zlib is a free compression library (a DLL) on which the popular gzip utility is built.  In this article, we'll see how to use the zlib functions to compress and decompress data in memory; that is, without needing to use a temporary file.  We'll be c…
A theme is a collection of property settings that allow you to define the look of pages and controls, and then apply the look consistently across pages in an application. Themes can be made up of a set of elements: skins, style sheets, images, and o…
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
This video discusses moving either the default database or any database to a new volume.

744 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now