ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ LZEXPAND Tutorial ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ by Bumblebee/29a Introduction ÄÄÄÄÄÄÄÄÄÄÄÄ This tutorial explains how to expand a compressed file using win API and MS COMPRESS.EXE. It is a lame tool to compress files with a LZ algo and the format required by LZEXPAND.DLL. Look at tools section at this zine and you'll find COMPRESS.EXE there. We can compress a dropper, as example, and put inside your virus body. Due the dropper was compressed using an external program we don't need to care about the compression algo. When we need the file uncompressed we don't need to carry the expand routines inside virus body because winshit provides us a simple way to expand it using standard win32 API. Even LZ77 doesn't gives us wonder compression ratios it's interesting check it coz it could work as encryption and may be your huge 20 kbs infector that has a dropper for irc will reduce it's size in some kbs. Test it and if you feel it's worth it: let's LZEXPAND it! What is a LZEXPAND.DLL? ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ It's simply a library that contains some functions to manage the LZed files within our win32 appz. Let's check what is provided: LZCopy Copies a compressed file into an uncompressed one LZOpenFile Opens a compressed file and returns a handle LZClose Closes a file handle by LZOpenFile There are other functions but we are going to use only those. Get LZEXPAND.DLL ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ We need to load LZEXPAND.DLL library and get the address of the func in order to use them. It is done as usual. Notice we call LZ32.DLL coz we are running a 32 bits app and LZEXPAND.DLL is a lame NE file :) Let's show ya an example: ; ebp assumed to be delta offset ; some API addr required: ; LoadLibraryA GetProcAddress LzExpandZs db 'LZ32.dll',0 ; this is the wrapper for 32bits LzExpandHnd dd 0 LzFuncZs0 db 'LZCopy',0 LzFuncZs1 db 'LZOpenFileA',0 LzFuncZs2 db 'LZClose',0 LzFuncZsA dd offset LzFuncZs0,offset LzFuncZs1 dd offset LzFuncZs2 LzFuncAddr: _LZCopy dd 0 _LZOpenFile dd 0 _LZClose dd 0 lea eax,LzExpandZs+ebp push eax call dword ptr [_LoadLibraryA+ebp] or eax,eax jz LzExpandNotLoaded ; failed loading dll mov dword ptr [LzExpandHnd+ebp],eax lea esi,LzFuncZsA+ebp ; array func stringz lea edi,LzFuncAddr+ebp ; array to store addresses mov ecx,3 GetLzFuncLoop: mov edx,dword ptr [esi] add edx,ebp push esi edi ecx push edx ; api strz push dword ptr [LzExpandHnd+ebp] ; dll handle call dword ptr [_GetProcAddress+ebp] or eax,eax pop ecx edi esi jz LzExpandFuncNotFound ; failed getting api mov dword ptr [edi],eax add esi,4 add edi,4 loop GetLzFuncLoop Do not copy and paste. Understand it! And remember to call FreeLibrary when LZEXPAND work is done. I think can be easily translated to HLL. Only asm example :) I'm sure this code is very basic and you already know it. Using LZEXPAND.DLL ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ A LZEXPAND session goes as folows: 1. LZOpenFile source (compressed) 2. LZOpenFile destination (where to place uncompressed) 3. LZCopy source over destination 4. LZClose source 5. LZClose destination Let's see the funcs protos: int LZOpenFileA(LPTSTR filename,LPOFSTRUCT reOpenBuf, WORD style) ----------------------------------------------------------------- filename: The zero string of the file to open. reOpenBuf: Pointer to a struct that will be filled. It's used for for re-open matters... OFSTRUCT struc cBytes db ? ; lenght of the struct fFixedDisk db ? ; non zero if file on HDD nErrCode dw ? ; DOS error code if open fails Reserved dw ?,? szPathName db 128 dup(?) ; path name OFSTRUCT ends style: Action to take. OF_READ equ 0000h OF_WRITE equ 0001h OF_CREATE equ 1000h OF_... The func returns a file handle or a valid handle on error. long LZCopy(int source, int destination) ---------------------------------------- source: a file hadle from LZOpenFile with OF_READ style. destination: a file hadle from LZOpenFile with OF_WRITE style. Returns the size of the destination file and < 0 value for error. void LZClose(int handle) ------------------------ handle: handle of file from LZOpenFile to close. Here follows an example that expands a file called file.tx_ into a file.txt. Notice that delta offset is not needed so ebp has been removed. I tried to use previous pieze to get APIs from LZEXPAND.DLL with minium changes. ; cut here ---------------------------------------------------------------- ; ; This is an exaple of the use of LZEXPAND.DLL ; Notice the ebp stuff is removed due is not required! ; Expands file.tx_ to file.txt. ; Coded by Bumblebee/29a ; .486p locals .model flat,STDCALL extrn ExitProcess:PROC extrn LoadLibraryA:PROC extrn GetProcAddress:PROC extrn FreeLibrary:PROC OFSTRUCT struc cBytes db ? ; lenght of the struct fFixedDisk db ? ; non zero if file on HDD nErrCode dw ? ; DOS error code if open fails Reserved dw ?,? szPathName db 128 dup(?) ; path name OFSTRUCT ends OF_READ equ 0000h OF_WRITE equ 0001h OF_CREATE equ 1000h .DATA LzExpandZs db 'LZ32.dll',0 ; remeber: use the wrapper LzExpandHnd dd 0 LzFuncZs0 db 'LZCopy',0 LzFuncZs1 db 'LZOpenFileA',0 LzFuncZs2 db 'LZClose',0 LzFuncZsA dd offset LzFuncZs0,offset LzFuncZs1 dd offset LzFuncZs2 LzFuncAddr: _LZCopy dd 0 _LZOpenFileA dd 0 _LZClose dd 0 ofStruct OFSTRUCT file_in db 'file.tx_',0 file_out db 'file.txt',0 hnd_in dd 0 hnd_out dd 0 .CODE inicio: push offset LzExpandZs call LoadLibraryA or eax,eax jz LzExpandNotLoaded ; failed loading dll mov dword ptr [LzExpandHnd],eax lea esi,LzFuncZsA ; array func stringz lea edi,LzFuncAddr ; array to store addresses mov ecx,3 GetLzFuncLoop: mov edx,dword ptr [esi] push esi edi ecx push edx ; api strz push dword ptr [LzExpandHnd] ; dll handle call GetProcAddress or eax,eax pop ecx edi esi jz LzExpandFuncNotFound ; failed getting api mov dword ptr [edi],eax add esi,4 add edi,4 loop GetLzFuncLoop push OF_READ push offset ofStruct push offset file_in call dword ptr [_LZOpenFileA] cmp eax,0 jb LzExpandFuncFailed mov dword ptr [hnd_in],eax push OF_WRITE OR OF_CREATE push offset ofStruct push offset file_out call dword ptr [_LZOpenFileA] cmp eax,0 jb LzExpandFuncFailed mov dword ptr [hnd_out],eax push dword ptr [hnd_out] push dword ptr [hnd_in] call dword ptr [_LZCopy] push dword ptr [hnd_out] call dword ptr [_LZClose] push dword ptr [hnd_in] call dword ptr [_LZClose] LzExpandFuncFailed: push dword ptr [LzExpandHnd] call FreeLibrary LzExpandFuncNotFound: LzExpandNotLoaded: push 0h call ExitProcess Ends End inicio ; cut here ---------------------------------------------------------------- As you can see it's very easy :) Where to use it ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ As i said in the introduction LZ algo that uses MS Compress and LZEXP is not very good. We will get better compression ratio with huge files. The only way to know if we can use it in our projects it's just doing some tests. Let me show you a nice example of LZEXPAND usage: We have a two-parts virus: a. PE infector coded in asm b. Word Macro If our PE infector is less than 4 kbs there is nothing to compress but if the macro part is about 100 kbs... :). The idea is to compress the word doc and store compressed into the PE part. When the PE pieze runs it drops an uncompressed sample of the doc. The doc is a little installer that creates some macroz and... blah blah. We get: Inside PE files Macros /----------------------------------------\ With LZEXPAND | 4 + n kbs | 100 + (4+n) kbs | Without LZEXPAND | 4 + 100 kbs | 100 + (4+100) kbs | \----------------------------------------/ With n less than 100 kbs. I've tested with Plage2000 and i've got: Un-compressed: 102.400 bytes Compressed: 32.597 bytes As you can see, in this example we can use LZEXPAND very fine. Last words ÄÄÄÄÄÄÄÄÄÄ Micro$oft Winblows if full of shit we can use for our own profit. We only need to see what it brings and just get it. Now you can use simple compression in your projects with the APIs provided by M$. I hope you enjoy this little article. Nice coding! The way of the bee