flat assembler
Message board for the users of flat assembler.

Index > Main > DeLL HeLL | War on bloat in "SYSTEM32"

Author
Thread Post new topic Reply to topic
DOS386



Joined: 08 Dec 2006
Posts: 1905
DOS386 13 Jun 2010, 04:22




This is about DLL's (again), cool set of examples showing:

Smile How to use DLL's in Windows and DOS
Smile How to brew a DLL using format binary
Smile How to brew PIC
Smile How to reduce bloat compared to format PE (famous "format PE" requires private sections for all imports, exports and reloxxx, "format binary" can put all into 1 section, and further optimize by minimizing align losses)
Smile How to reduce bloat in WINDAUBE\SYSTEM32\ directory, just copy the 10 DLL's (after renaming) there in, confirming "YES" to possible "Overwrite?" questions (trivial task but seems very difficult to do on Wista, bug the author of the thing Sad ...)
Smile How to use the MZ stub to store useful stuff (famous "format PE" adds a faulty stub at best)

Download now : id=5001 DLL.ZIP (252 KiO) updated 2014-Jul-12

Binaries only : HXDLL.ZIP (5 KiO)

There are 2 subdirectories in the package:

### HXDLL + HDLLSRC (works in Wista, XP, ME, and DOS)

10 DLL's to be copied into "SYSTEM32" directory or used in DOS, see shot:

Image

Of course one could completely kick those 10 DLL's instead of replacing them, this however has the flaw that some applications don't work anymore then Sad

### DLLEXAM (works in Wista, XP, ME, and DOS)

EXE + DLL example, note that both files have just 1 KiO of bloat (the very smallest valid PE size, compared to Tomasz's "official" example with 1.5 + 3 KiO), and are "smarter" (in Tomasz's example it is somewhat obscure what is supposed to happen at all, and what effect comes from the EXE and what from the DLL), also they are fully PIC Smile (work also with paging OFF) and don't require any include files to compile, see shot:

Image

P.S.: there indeed used to be a post about very same Dell Hell thing years ago, I had deleted the old one, because the code was faulty (it really sucked Sad , nevertheless nobody dared to complain Shocked ...), and there were no answers at all Sad

Code:
        call   dword [(GetTickCount-imp_center)+ebx]
        xchg   esi, eax       ; Backup start time into ESI

        mov    eax, esp
        pushd  $10            ; MB type: "error" with one "OK" button
        push   eax
        push   eax
        pushd  0              ; ZERO ???
        call   dword [(MessageBoxA-imp_center)+ebx]

        call   dword [(GetTickCount-imp_center)+ebx]
        sub    eax, esi       ; LET EAX:=EAX-ESI

        add    esp, 64

        pope   edi
        pope   esi
        pope   ebx
        ret    4              ; Throw away one argument, return result in EAX
        ;-------

; ----------------------------------------------------------------------

if ( ($ mod 4) > 0 )
  db ( (3) - ($+3) mod 4 ) dup(0)
  ; Align to 4 // this ^^^ line fails if already aligned
end if

; ----------------------------------------------------------------------

; ######## Import & Export and Relox blocks (no private section) ########

; ----------------------------------------------------------------------

llimpbeg:

dd 0, 0, 0, (dgjpp_kernel_name-ccbase), (dgjpp_kernel_table-ccbase)
dd 0, 0, 0, (dgjpp_user32_name-ccbase), (dgjpp_user32_table-ccbase)
dd 0, 0, 0, 0 ; Missing ZERO is below

llrelbeg:

dd 0, 8 ; Fixed 8 Bytes | Note that one ZERO is used twice Wink

llexpbeg:

dd 0, 0, 0                    ; Characterum, Timestamp, Version
dd (dgjpp_dll_name-ccbase)
dd 1, 2, 2                    ; OrdinalBase, Functions, Names
dd (dgjpp_functions-ccbase)
dd (dgjpp_names_list-ccbase)
dd (dgjpp_ordinals-ccbase)

dgjpp_kernel_table:

GetTickCount: dd (_GetTickCount-ccbase)
dd 0
    


(download attach for full source code)

PP.SS. : as you can see, some files are missing in the package above, PM if you need - at your own risk - the full non-public package (1.4 MiO) Neutral

Related discussions:

http://board.flatassembler.net/topic.php?t=13383

http://board.flatassembler.net/topic.php?t=4509

_________________
Bug Nr.: 12345

Title: Hello World program compiles to 100 KB !!!

Status: Closed: NOT a Bug


Last edited by DOS386 on 12 Jul 2014, 09:25; edited 12 times in total
Post 13 Jun 2010, 04:22
View user's profile Send private message Reply with quote
mindcooler



Joined: 01 Dec 2009
Posts: 423
Location: Västerås, Sweden
mindcooler 13 Jun 2010, 14:57
Where were you when I needed you?! Smile

http://board.flatassembler.net/topic.php?t=11579

Edit: Now I see you were right there! :b I missed your post..

07 Jun 2010, 07:06

_________________
This is a block of text that can be added to posts you make.
Post 13 Jun 2010, 14:57
View user's profile Send private message Visit poster's website MSN Messenger ICQ Number Reply with quote
flat_user



Joined: 01 Jun 2010
Posts: 13
flat_user 13 Jun 2010, 15:26
Quote:
How to use the MZ stub to store useful stuff (famous "format PE" adds a faulty stub at best)

Instead of storing the unnecessary ms-dos stub in the mz header, I would rather store imports or the pe header itself in it.
This had been useful, since if you just cut the stub, you would have saved 20 bytes.
Also why did you do all stuff hardcoded? Just use labels:
Code:
  db start_of_pe,0,0,0                 ; PE begins here 
  ;[...]
start_of_pe:
  db "PE", 0, 0 ; Signature    


Quote:
How to reduce bloat compared to format PE (famous "format PE" requires private sections for all imports, exports and reloxxx, "format binary" can put all into 1 section, and further optimize by minimising align losses)

Actually you do not have to create a seperate section for each of those data-directories. Just use the data-directive and pack all into one section. It will be of the same size as your manually, not very dynamically created pe-file.

Also in my opinion your examples seem to be kind of confused and too static, means at least for me they're not very helpful
Post 13 Jun 2010, 15:26
View user's profile Send private message Reply with quote
mindcooler



Joined: 01 Dec 2009
Posts: 423
Location: Västerås, Sweden
mindcooler 13 Jun 2010, 15:36
flat_user wrote:

Instead of storing the unnecessary ms-dos stub in the mz header, I would rather store imports or the pe header itself in it.
This had been useful, since if you just cut the stub, you would have saved 20 bytes.


But what good are those bytes when you need to align the first section to $200? I have almost $100 "useless" empty bytes between the headers and the code section.

_________________
This is a block of text that can be added to posts you make.
Post 13 Jun 2010, 15:36
View user's profile Send private message Visit poster's website MSN Messenger ICQ Number Reply with quote
flat_user



Joined: 01 Jun 2010
Posts: 13
flat_user 13 Jun 2010, 16:18
If you argued like this, DOS386's approach would be useless as well.
Use such space for more section headers or try to embed strings or other data in there.
Post 13 Jun 2010, 16:18
View user's profile Send private message Reply with quote
mindcooler



Joined: 01 Dec 2009
Posts: 423
Location: Västerås, Sweden
mindcooler 13 Jun 2010, 16:21
flat_user wrote:

Use such space for more section headers or try to embed strings or other data in there.


More section headers -> more sections -> more waste.

The only data you can put there is data that is only used by your program, not passed to system calls and the like, as only your process can read them.

_________________
This is a block of text that can be added to posts you make.
Post 13 Jun 2010, 16:21
View user's profile Send private message Visit poster's website MSN Messenger ICQ Number Reply with quote
score_under



Joined: 27 Aug 2009
Posts: 27
score_under 14 Jun 2010, 20:04
DOS386 wrote:

Smile How to reduce bloat compared to format PE (famous "format PE" requires private sections for all imports, exports and reloxxx, "format binary" can put all into 1 section, and further optimize by minimising align losses)

I was once introduced by Tomasz to the "data <x>" directive.
I now write all my dlls with size (and complete unreadability Very Happy) in mind:
Code:
format PE GUI 4.0 DLL
;note, if "entry" is omitted in a DLL it acts the same as an entry with "mov eax,1/retn"
section '.text' code data readable writeable executable
data import
library user32,'user32.dll'
import user32,MessageBox,'MessageBoxA'
end data
title db 'Hi',0
text db 'This function should do something. Pretend it just did.',0
align 0x10
MyFunc:
  push 0
  push title
  push text
  push 0
  call [MessageBox]
  ret
data export
export 'MyDll.dll',MyFunc,'MyFunc'
end data
data fixups
end data    
Post 14 Jun 2010, 20:04
View user's profile Send private message Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1905
DOS386 27 Jun 2010, 10:46
> Instead of storing the unnecessary ms-dos stub in the mz header,
> I would rather store imports or the pe header itself in it.

My example doesn't have any "unnecessary ms-dos stuff" at all Smile

> Actually you do not have to create a seperate section for each of those
> data-directories. Just use the data-directive and pack all into one section.
> It will be of the same size as your manually, not very dynamically created pe-file.

Interesting ... although it still won't fix the stub Sad
Post 27 Jun 2010, 10:46
View user's profile Send private message Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1905
DOS386 12 Jul 2014, 09:23
Updated (see top post), more DLL's included, now Get****FileName* tested (but not yet implemented)

Image

works ^^^ on Win8/XXX-64 too Wink

Image

this happens ^^^ if you drop my WLDAP32.DLL into SYSTEM32 directory Wink

Code:
; SUB SSCLEARSETOFN | IN "vvunicrap" "vvmustex" | OUT EDI
; Trash EAX , ECX , EDI
; Trash "bbgetstring" , "bbbuf256a" (struct) , "bbbuf256b"  (out string)

; The horrible thing eats 4 strings as input :
; - Title (may be empty but we do set it)
; - Preselected filename (may be empty, and we leave it empty)
; - 2 strings about the filter (may be empty ??? we do set it)

ssclearsetofn:

        movntq eax, 0
        movntq ecx, 0
        mov    cl, 128
        lea    edi, [bbbuf256a]   ; Clear "bbbuf256a" and "bbbuf256b"
        push   edi
        rep    stosd
        pope   edi

if ((bbbuf256a+256-bbbuf256b)<>0)
  err "(bbbuf256a+256)<>bbbuf256b"
end if

        mov    al, 30             ; "All silly files *.*  Testing" (2Cool
        call   ssgetstringcopy

        mov    cl, 0
        mov    [eax+15], cl
        mov    [eax+19], cl
        mov    [eax+20], cl
        mov    ch, 65             ; "A"
        cmp    [vvunicrap], byte 0
        je     short @f
        add    ch, 22             ; "A" -> "W"
@@:     mov    [eax+28], ch
        mov    [eax+29], cl       ; TER-ZERO

        cmp    [vvunicrap], byte 0
        je     short no_uni_expand

        push   edx
        movntq edx, 0             ; Value transfer
        movntq ecx, 0             ; Index
        mov    cl, 29
@@:     mov    dl, [eax+ecx]
        mov    [eax+2*ecx], dx
        dec    ecx
        jns    short @b
        pope   edx

no_uni_expand:

        mov    [edi], byte 76     ; "lStructSize" | Needed ???

        mov    [edi+12], eax      ; Filter | 2 str's | 21 char's incl. ZERO's

        lea    ecx, [bbbuf256b]   ; It's empty on entry Wink
        mov    [edi+28], ecx      ; In and out buffer | 256 Byte's

        lea    ecx, [eax+21]      ; Last use of EAX address
        mov    al, 252            ; Buffer size limit
        cmp    [vvunicrap], byte 0
        je     short @f
        add    ecx, 21            ; Move up string address in Byte's
        mov    al, 126            ; DIV amount of char's fitting into buffer
@@:     mov    [edi+32], al       ; "nMaxFile"
        mov    [edi+48], ecx      ; "lpstrTitle"

        mov    eax, $1212'0004    ; Add $1000 for load (must exist)
        cmp    [vvmustex], byte 0
        je     short @f
        add    ah, 16             ; ADDNTQ EAX, $1000
@@:     mov    [edi+52], eax      ; "Flags"

        ret
        ;----
    


If you still have ME then you can find out that Get****FileNameW is recognized there but not implemented either Wink

Code:
'' This vvv sucks
if ((bbbuf256a+256-bbbuf256b)<>0)
  err "(bbbuf256a+256)<>bbbuf256b"
end if
'' This ^^^ sucks
    


Don't use this anymore, use assert

Code:
assert ((bbbuf256a+256-bbbuf256b)=0)    


UPDATED 2014-Jun-12 (added "IPHLPAPI.DLL")
Post 12 Jul 2014, 09:23
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8358
Location: Kraków, Poland
Tomasz Grysztar 12 Jul 2014, 12:47
DOS386 wrote:
(famous "format PE" adds a faulty stub at best)
DOS386 wrote:
Interesting ... although it still won't fix the stub Sad

fasm's "format PE" allows you to use any stub you want (with the ON operator). If the file you specify is not an MZ executable, fasm treats it as .COM and tries to do .COM->MZ conversion (not exactly 100% compatible, but usually enough).

Some of the old fasm releases (like 1.40) had a Win32 fasm.exe that used the DOS version of fasm for a stub.
Post 12 Jul 2014, 12:47
View user's profile Send private message Visit poster's website Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1905
DOS386 13 Jul 2014, 11:03
Quote:
fasm's "format PE" allows you to use any stub you want (with the ON operator). If the file you specify is not an MZ executable, fasm treats it as .COM and tries to do .COM->MZ conversion (not exactly 100% compatible, but usually enough).


Thanks, I had known this ... but the built-in stub is more MS-compatible than useful. And, the "ON" operator depends from external file ( SS -> NOT-SO due to unpredictable content of external file ) .

> Some of the old fasm releases (like 1.40) had a Win32 fasm.exe
> that used the DOS version of fasm for a stub.

Interesting Smile

Actually I had made a suggestion how to make the stub "automatically" more useful only 4 years ago.

(and I had registered here only 8 years ago ... incredible how the time is racing by)
Post 13 Jul 2014, 11:03
View user's profile Send private message Reply with quote
ACP



Joined: 23 Sep 2006
Posts: 204
ACP 13 Jul 2014, 22:25
DOS386 wrote:

Thanks, I had known this ... but the built-in stub is more MS-compatible than useful. And, the "ON" operator depends from external file ( SS -> NOT-SO due to unpredictable content of external file ) .


Could you please elaborate more on this. AFAIK FASM is generating PE files compliant with MS PE+ COFF specs. How can than a stub be more MS-compatible than useful? Unless you specify your own stub what else do you expect?



I'm sorry but I fail to see what is more useful in your proposal? If you are targeting normal user he probably does not have a clue what is "Win64 GUI executable" for example... either you run PE file in Windows compatible environment or not. If not there is a message that can be displayed assuming you are running the file under DOS compatible environment. You can always include your own stub, unless you are using stub from DOS extender, but those then to give different message.
Post 13 Jul 2014, 22:25
View user's profile Send private message Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1905
DOS386 15 Jul 2014, 08:04
> How can than a stub be more MS-compatible than useful?

The way that cca 1'000'000'000 compilers and linkers do. So far only WLINK does put somewhat useful data into the stub.

> Unless you specify your own stub what else do you expect?

FASM could put some useful info into the default PE stub.

> targeting normal user he probably does not have a clue
> what is "Win64 GUI executable"

It explains why the thing doesn't run on Win32. And if some dumb user has no clue what Win64 or GUI is, it at least doesn't hurt him. And he maybe could read out the name of the program the file holds or belongs to, if he accidentally found a way how to display the file.

> I fail to see what is more useful in your proposal?

* If you accidentally rename a PE file, you can look at the stub what it could be

* The stub could hold a human-readable version info

PS: check out my "Ultimate "waveOut" test / Ynsane sound PLAYER" too
Post 15 Jul 2014, 08:04
View user's profile Send private message Reply with quote
baldr



Joined: 19 Mar 2008
Posts: 1651
baldr 15 Jul 2014, 12:53
DOS386,

It made me curious why db ( (3) - ($+3) mod 4 ) dup(0) should fail if $ mod 4 == 0. Actually it could be so for fasm 1.62 (when dup was introduced) up to 1.69.19 (which allowed zero count for it).

Anyway, you can use times ever since fasm 1.0; for power-of-2 alignment something like times -$ and 3: db 0 looks better, I think; rb -$ and 3 could be even better. Wink

Addendum:

While I was pondering about a solution for xorpd's bonus exercise 2.2.8 ( using mov, add and sub only), I'd recollected somewhat limited (due to possible overflow) but otherwise elegant way to do the very same thing for an arbitrary alignment modulo: rb ((m-1)*$) mod m.
Post 15 Jul 2014, 12:53
View user's profile Send private message Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1905
DOS386 31 Jul 2014, 19:43
> It made me curious why db ( (3) - ($+3) mod 4 ) dup(0) should
> fail if $ mod 4 == 0. Actually

it most likely did fail when I wrote or pirated this code. Unfortunately I didn't bother to check with every single new version of FASM whether it still securely fails.

PS: did you get sound?
Post 31 Jul 2014, 19:43
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.