News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Rich Signature Solutions

Started by RotateRight, March 06, 2010, 06:35:01 PM

Previous topic - Next topic

RotateRight

Consider this small C program:

/****************/
/* MessageBox.c */
/****************/

#include <windows.h>

void Entry(void);

void Entry(void)
{
    MessageBox(NULL, "PellesC", "Hello!", MB_OK);
    ExitProcess(0);
}


Use PellesC to create it with something like:

@echo off

rem ***************
rem * PellesC.bat *
rem ***************

set PATH=\PellesC\Bin
set INCLUDE=\PellesC\Include;\PellesC\Include\Win
set LIB=\PellesC\Lib\Win

pocc -Tx86-coff -Gz -Ze MessageBox.c
polink -entry:Entry@0 -nodefaultlib -subsystem:windows MessageBox.obj Kernel32.lib User32.lib

del MessageBox.obj

pause


Once it is created you will have an executable named MessageBox.exe.

Some notes about the produced file:

It has a size of 2,048 bytes.
It has three sections.
It has .text, .data, and .rdata sections.
The strings were placed in the .rdata section.
The import table was placed in the .data section.

Then consider this MASM program:

;******************
;* MessageBox.asm *
;******************

.386
.model flat, stdcall
option casemap:none

public start

ExitProcess proto :dword
MessageBoxA proto :dword, :dword, :dword, :dword
MessageBox equ <MessageBoxA>

.data

strCaption db 'Masm', 0
strText db 'Hello!', 0

.code

start:
        invoke  MessageBox, 0, offset strCaption, offset strText, 0
        invoke  ExitProcess, 0

end start


A small batch file to create it:

@echo off

rem ******************
rem * MessageBox.bat *
rem ******************

set Path=\Masm32\Bin
set Lib=\Masm32\Lib

ml /c /coff MessageBox.asm
link /subsystem:windows /entry:start MessageBox.obj kernel32.lib user32.lib

del MessageBox.obj

pause


It has a size of 2,560 bytes.
It has three sections.
It has .text, .data, and .rdata sections.
The strings were placed in the .data section.
The import table was placed in the .rdata section.

Of course there are things that could be done to decrease size:

In the C program, one could have forced the strings
to the .data section with something like:

char strCaption[] = "PellesC", strText[] = "Hello!";
MessageBox(NULL, strCaption, strText, MB_OK);

In the Asm program, you might use .const instead of .data.

But, the attempt here is to get two programs that are "similar"
and contain the same number of sections.

The C program is 2,048 bytes, yet the Asm program is 2,560.
They both have three sections.  What's the difference?
Since we all know that our section size here is 512 byes,
the difference is in the header size.  PellesC used a
header of 512 bytes, the Asm version used 1024 bytes.

In this case, the larger size resulted from the "Rich Signature"
that MS link.exe placed in the header.  Basically this "watermark"
can identify the tools that were used to build the EXE.  The "compids"
can also provide information about libraries used.  Another
fine feature of MS products (sarcasm).

To learn more, go here:

http://trendystephen.blogspot.com/2008/01/rich-header.html

and here:

http://ntcore.com/files/richsign.htm

One solution to this annoying little problem is to patch the linker.

If you do this, you're on your own (and don't forget to make a backup).

Open \masm32\bin\link.exe (version 5.12) in a hex editor.

You need to NOP two bytes.

8B8D E0010000  mov ecx, dword ptr [ebp+1E0]
894424 10      mov dword ptr [esp+10], eax
03C8           add ecx, eax                    <-- NOP this instruction
898D E4010000  mov dword ptr [ebp+1E4], ecx


Go To Offset 4511B:
                                            -- --
00045110:  ff 8b 8d e0 01 00 00 89 44 24 10 03 c8 89 8d e4

Change the 03 C8 to NOPs 90 90

00045110:  ff 8b 8d e0 01 00 00 89 44 24 10 90 90 89 8d e4

The other solution is to write a program to do the job for you.

Attached is RichSignature.zip.  Just run RichRemove.exe as a
post link step.

It doesn't always reduce the program size.  It does reduce it
when the crap that was added crosses the next boundry of
File Alignment.  But, it always removes the watermark.

I'm a bit new to this PE format stuff.  So don't run it against
something important. 

If you improve the code, how about posting it back!  I'm sure that
many bases weren't covered in the code.  Something to play with.

Hope this might be worth something to someone.

Mark




jj2007

1024 bytes:
include \masm32\include\masm32rt.inc

.code
AppName db "Masm32:", 0
HelloW db "Hello World", 0

start: MsgBox 0, addr HelloW, addr AppName, MB_OK
exit

end start

OPT_Linker polink
OPT_DebugL /MERGE:.data=.rdata /MERGE:.rdata=.text ; linker options for ultra short executables

The other question is what heuristic AV scanners have to say on that ;-)

dedndave

i wouldn't be patching the linker without a good reason  :bg
but, if you use polink, it will probably be 2 Kb

jj2007

Quote from: dedndave on March 06, 2010, 08:35:30 PM
but, if you use polink, it will probably be 2 Kb
1k with /MERGE:.data=.rdata /MERGE:.rdata=.text, as shown above

lingo

RotateRight,
It is very old stuff... :wink
You can look back at 2003 when I "invented" the Rich structure and NOP, NOP (90h, 90h) (see: http://www.asmcommunity.net/board/index.php?topic=10554.120) just to answer TheSvin's question about it. 
See S.T.A.S.'s "Lingo, thanks a lot!" and CodeTester's "Lingo , thank you very much for your interesting post about the encrypted data in the DOS stub." here: http://www.asmcommunity.net/board/index.php?topic=14699.msg113971#msg113971

clive

Quote from: lingo on March 07, 2010, 12:32:26 PM
It is very old stuff...

Like 1998, when DanS (Dan Spalding) added in the Delayed Import stuff as well.

-Clive
It could be a random act of randomness. Those happen a lot as well.