; ;============================================================================= ;LZ32Decompression subroutines. ;All rights may be reserved by SexyDufus ;Disassembled by IDA v3.xx with little help of Green Monster ;-) ;============================================================================== ; ;Interface: ;int lz_decompresss(char *inbuf, char *outbuf, int size, char *buf) ; ;----------------------------------------------------------------------------- ;Decompress data from inbuf, write output to outbuf. ;External buffer (buf) used for dictionary. ;Returns number of bytes placed in outbuf. ;============================================================================= ; VarFrame struc ; vf_Const01FF dw ? ;Mask (perverted) vf_Const03FF dw ? ;Other one vf_Const07FF dw ? ;Third vf_Const0FFF dw ? ;Last ; vf_Sym1 dw ? ;Symbols vf_Sym2 dw ? ; vf_Sym3 dw ? ; ; vf_FreeSym dw ? ;Free symbol vf_CharCount dw ? ;Character count vf_DictSize dw ? ;Dictionary size vf_BitSize dw ? ;Bits in char vf_SimpleChar db ? ;Character vf_CharToLink db ? ;explains itself ; vf_InBufRelPos dw ? ;Position in the input buffer field_1A dw ? ; vf_OutBufPos dd ? ;Position in the output buffer field_20 dw ? ; field_22 dw ? ; ;Parameters vf_InBuf dd ? ;char *inbuf vf_OutBuf dd ? ;char *outbuf vf_SuxxSize dd ? ;char *size (not used) vf_Malloced dd ? ;char *buf (dictionary) VarFrame ends ; ; ;============================================================================= ;Main subroutine ;============================================================================= lz_decompress proc near ; sub eax, eax ; push eax ;Structure init push eax ; push 9 ; push 2000000h ; push 1020000h ; push eax ; push 0FFF07FFh ;Perverted masks push 3FF01FFh ; mov ebp, esp ; ; get_next_sym: ; call Get_Sym ;Get symbol cmp ax, 101h ; 101h - end of data jz lzd_exit ; cmp ax, 100h ; 100h - dictionary reset jnz short other_syms ; ; call lzd_init ;Reset ; call Get_Sym ; mov [ebp+VarFrame.vf_Sym1], ax ; mov [ebp+VarFrame.vf_Sym2], ax ; mov [ebp+VarFrame.vf_CharToLink], al ; mov [ebp+VarFrame.vf_SimpleChar], al ; call Save_Char ;First symbol is always simple jmp short get_next_sym ; ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ; other_syms: ; mov [ebp+VarFrame.vf_Sym1], ax ; mov [ebp+VarFrame.vf_Sym3], ax ; cmp ax, [ebp+VarFrame.vf_FreeSym] ;Symbol is already in jl short already_in_dict ;dictionary? ; movzx eax, [ebp+VarFrame.vf_Sym2] ; mov [ebp+VarFrame.vf_Sym1], ax ; movzx eax, [ebp+VarFrame.vf_SimpleChar] push eax ;Leave it in stack inc [ebp+VarFrame.vf_CharCount] ; ; already_in_dict: ; cmp [ebp+VarFrame.vf_Sym1], 0FFh ; jle short one_time_again ; ; ; movzx ebx, [ebp+VarFrame.vf_Sym1] ; call _Calc_Sym_Pos ; mov al, [ebx+2] ; push eax ;Create chain in stack inc [ebp+VarFrame.vf_CharCount] ; movzx eax, word ptr [ebx] ; mov [ebp+VarFrame.vf_Sym1], ax ; jmp short already_in_dict ; ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ; one_time_again: ; movzx eax, [ebp+VarFrame.vf_Sym1] ; mov [ebp+VarFrame.vf_SimpleChar], al ; mov [ebp+VarFrame.vf_CharToLink], al ; push eax ; inc [ebp+VarFrame.vf_CharCount] ; movzx ecx, [ebp+VarFrame.vf_CharCount] ; jcxz no_chars ; ; save_from_stack: ;Write chain from stack pop eax ; call Save_Char ;into output stream loop save_from_stack ; ; no_chars: ; mov [ebp+VarFrame.vf_CharCount], cx ; ; call Add_Chain ; movzx eax, [ebp+VarFrame.vf_Sym3] ; mov [ebp+VarFrame.vf_Sym2], ax ; movzx ebx, [ebp+VarFrame.vf_FreeSym] ; ; ; cmp bx, [ebp+VarFrame.vf_DictSize] ; jl get_next_sym ; ; ; ;-------->replaced<----------------- ; ; cmp [ebp+VarFrame.vf_BitSize], 0Ch ; cmp [ebp+VarFrame.vf_BitSize], MAX_BITS ;Check amount of bits ;-------->end<--------------------- ; jz get_next_sym ; ; inc [ebp+VarFrame.vf_BitSize] ;Increase it shl [ebp+VarFrame.vf_DictSize], 1 ;And dictionary size jmp get_next_sym ; ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ; lzd_exit: ; xchg eax, edi ;EAX = end-start = size sub eax, [ebp+VarFrame.vf_OutBuf] ; add esp, 20h ; retn 10h ; lz_decompress endp ; ; ;----------------------------------------------------------------------------- ;Calculate address of dictionary element from symbol nubmer ;----------------------------------------------------------------------------- _Calc_Sym_Pos proc near ; lea ebx, [ebx+ebx*2] ;EBX *= 3 add ebx, [ebp+VarFrame.vf_Malloced] ; retn ; _Calc_Sym_Pos endp ; ; ;----------------------------------------------------------------------------- ;Read symbol of variable size from the input stream ;----------------------------------------------------------------------------- Get_Sym proc near ; movzx eax, [ebp+VarFrame.vf_BitSize] ; add eax, dword ptr [ebp+VarFrame.vf_InBufRelPos] xchg eax, dword ptr [ebp+VarFrame.vf_InBufRelPos] mov ecx, 8 ; sub edx, edx ; div ecx ; /8 (bits per byte) add eax, [ebp+VarFrame.vf_InBuf] ; xchg eax, esi ; lodsw ;Load 3 bytes movzx ebx, ax ; lodsb ; movzx ecx, dx ; jcxz getsym_exit ; ;Select what we need select_bits: ; shr al, 1 ; rcr bx, 1 ; loop select_bits ; ; getsym_exit: ; movzx eax, bx ; movzx ebx, [ebp+VarFrame.vf_BitSize] ; ; ;------------>replaced<--------------------------------- ; ; sub ebx, 9 ; ; and ax, [ebp+ebx*2+VarFrame.vf_Const01FF] ; mov cl, bl ; xor ebx, ebx ; inc ebx ; shl bx, cl ; dec bx ; and ax, bx ; ; ;------------>end<-------------------------------------- ; ; retn ; Get_Sym endp ; ; ;----------------------------------------------------------------------------- ;Dictionary reset ;----------------------------------------------------------------------------- lzd_init proc near ; mov [ebp+VarFrame.vf_BitSize], 9 ;Size in bits mov [ebp+VarFrame.vf_DictSize], 200h ;Dictionary size mov [ebp+VarFrame.vf_FreeSym], 102h ;First free symbol retn ; lzd_init endp ; ; ;----------------------------------------------------------------------------- ;Write char into output stream ;----------------------------------------------------------------------------- Save_Char proc near ; mov edi, [ebp+VarFrame.vf_OutBufPos] ; add edi, [ebp+VarFrame.vf_OutBuf] ; stosb ; inc [ebp+VarFrame.vf_OutBufPos] ; retn ; Save_Char endp ; ; ;----------------------------------------------------------------------------- ;Write links into the dictionary ;----------------------------------------------------------------------------- Add_Chain proc near ; movzx ebx, [ebp+VarFrame.vf_FreeSym] ; call _Calc_Sym_Pos ; movzx eax, [ebp+VarFrame.vf_CharToLink] ; mov [ebx+2], al ; movzx eax, [ebp+VarFrame.vf_Sym2] ; mov [ebx], ax ; inc [ebp+VarFrame.vf_FreeSym] ; retn ; Add_Chain endp ; ; ; ;============================================================================= ;LZ32Compression subroutines. ;All rights may be reserved by SexyDufus [nah - SD;] ;Disassembled by IDA v3.xx with little help of Green Monster ;-) ;============================================================================== ; ;Interface: ;int lz_compresss(char *inbuf, char *outbuf, int size, char *buf) ; ;----------------------------------------------------------------------------- ;Compresses $size bytes from inbuf, writes output to outbuf. ;Uses external buffer (buf) to store dictionary ;Returns size of the compressed data ;============================================================================= ; include lzcd.asi ;--------------------------------------------------- ;Local variables structure (one for both subroutines) ProcFrame struc ; FirstSym dw ? ;First symbol Link dw ? ;Link DictBound dw ? ;Current dictionary limit BitsPerSym dw ? ;Bits in the output element ;(increases as the dictionary ;becomes full) ; NextInChar db ? ;Next char in the input stream field_9 db ? ; something field_A db ? ; other something field_B db ? ; third one ;Resume: NextChar was DWORD ;-) ; OutBufPos dd ? ;Current output pointer InBufRelPos dd ? ;Current input pointer RetEIP dd ? ;return address lz_compress ; ;Parameters: InBuf dd ? ;Input buffer OutBuf dd ? ;Output buffer SuxxSize dd ? ;Size of data in the output buffer Malloced dd ? ;Temporary buffer for dictionary ProcFrame ends ; ; ;------------------------------------------- ;Dictionary record ; ; ; TableItem struc ; Sym dw ? ;Symbol NextSym dw ? ;Next symbol NextChar db ? ;Next character in the chain TableItem ends ; ; ;============================================================================= ; Main function ;============================================================================= lz_compress proc near ; sub eax, eax ; push eax ;All fielst in the structure are push eax ;zeroed push eax ; push eax ; push eax ; mov ebp, esp ;EBP -> ProcFrame ; call lz_init ;Dictionary Reset ; ; sub eax, eax ; inc ah ;Symbol 100h = "dictionary reset" call Save_And_Step ;Dump it into the output ; call Get_Byte ;Get first byte ; @@compess_cycle: ;AL = character sub ah, ah ; ;AX = symbol @@get_chain: ;Searching for the unique string ;of characters mov [ebp+ProcFrame.FirstSym], ax call Get_Byte ; jb short lzc_exit ; ; mov [ebp+ProcFrame.NextInChar], al movzx ebx, [ebp+ProcFrame.FirstSym] call Search_Table ; jnb short @@get_chain ; ;Chain found call Set_Char_Link ; ;Dump symbol into the output push ebx ; movzx eax, [ebp+ProcFrame.FirstSym] call Save_And_Step ; pop ebx ; mov al, [ebp+ProcFrame.NextInChar] cmp bx, [ebp+ProcFrame.DictBound] jl short @@compess_cycle ; ;--------->replaced<------------------------ ; cmp [ebp+ProcFrame.BitsPerSym], 0Ch cmp [ebp+ProcFrame.BitsPerSym], MAX_BITS ;Index bits limit ;--------->end<----------------------------- jl short next_bit ; ; sub eax, eax ; inc ah ; 100h - dictionary reset call Save_And_Step ; call lz_init ; and reset it mov al, [ebp+ProcFrame.NextInChar] jmp short @@compess_cycle ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ; next_bit: ; inc [ebp+ProcFrame.BitsPerSym] ;Increase index shl [ebp+ProcFrame.DictBound], 1 ;Increase dictionary jmp short @@compess_cycle ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ; lzc_exit: ; movzx eax, [ebp+ProcFrame.FirstSym] call Save_And_Step ; mov eax, 101h ; 101h - end of chain call Save_And_Step ; xchg eax, edi ; sub eax, [ebp+ProcFrame.OutBuf] ;EAX = end-start = size add esp, 14h ; retn 10h ; lz_compress endp ; ; ;----------------------------------------------------------------------------- ;Dinctionary reset ;----------------------------------------------------------------------------- lz_init proc near ; pusha ; mov [ebp+ProcFrame.BitsPerSym], 9 ;9 bits ber each output symbol mov [ebp+ProcFrame.DictBound], 200h ;512 symbols in the dictionary sub eax, eax ; dec eax ; ;REset dictionary mov ecx, COMPR_BUFFER_SIZE/2 ; mov edi, [ebp+ProcFrame.Malloced] repe stosw ; ; mov [ebp+ProcFrame.Link], 102h ;First symbol ; ;(00-FF) - simpe symbols-characters ; (elementary dictionary) ; 100 - dictionary reset ; 101 - end of data ; 102-... - free symbols ; popa ; retn ; lz_init endp ; ; ;------------------------------------------------------------------------------------ ;Writes N bits (9-...) from the EAX to the output sream ;------------------------------------------------------------------------------------ Save_And_Step proc near ; push eax ; mov eax, [ebp+ProcFrame.OutBufPos] ;EAX -> bit int the output buffer movzx ecx, word ptr [ebp.ProcFrame.BitsPerSym] ;ECX = how many bits to write add [ebp+ProcFrame.OutBufPos], ecx ;Step ;Calculate the bit offset mov ecx, 8 ; sub edx, edx ; div ecx ; EDX = OutBufPos mod 8 add eax, [ebp+ProcFrame.OutBuf] xchg eax, edi ; EDI -> where to write pop eax ; ; mov ecx, edx ; sub edx, edx ; jcxz save_3bytes ; jump if on the byte's border ; shl eax, cl ; or al, [edi] ; ; save_3bytes: ; stosw ; shr eax, 10h ; stosb ; retn ; Save_And_Step endp ; ; ;----------------------------------------------------------------------------- ;Read character from the input sream in AL ;----------------------------------------------------------------------------- Get_Byte proc near ; mov esi, [ebp+ProcFrame.InBuf] ; ESI -> InBuf mov edi, [ebp+ProcFrame.InBufRelPos] ; EDI -> RelInBufPos cmp edi, [ebp+ProcFrame.SuxxSize] ; End already? jnb short byaka ; ; ; mov al, [esi+edi] ; Read inc [ebp+ProcFrame.InBufRelPos] ; clc ; retn ; byaka: ; stc ; retn ; Get_Byte endp ; ; ;----------------------------------------------------------------------------- ;Dictionary search ;----------------------------------------------------------------------------- Search_Table proc near call Calc_Sym_Pos ;ESI -> TableItem sub edi, edi ;EDI=0=success flag cmp [esi+TableItem.Sym], 0FFFFh ;Do we have such symbol? jz short not_found ; ; inc edi ;set flag movzx ebx, [esi+TableItem.Sym] ;EBX=symbol ; scan_chain: ; call Calc_Sym_Pos ; cmp [esi+TableItem.NextChar], al ;Is link exists? jnz short next_char ; ; clc ; movzx eax, bx ;EAX=chain symbol retn ; ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ; next_char: ; cmp [esi+TableItem.NextSym], 0FFFFh ;End of the chain jz short not_found ; movzx ebx, [esi+TableItem.NextSym] ;EBX=next symbol jmp short scan_chain ; ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ; not_found: ; stc ;No such chain retn ; Search_Table endp ; ; ;----------------------------------------------------------------------------- ;Calculate TableItem address in the dictionary using symbol in EBX ;----------------------------------------------------------------------------- Calc_Sym_Pos proc near ; lea esi, [ebx+ebx*4] ; ESI = EBX*sizeof(TableItem) add esi, [ebp+ProcFrame.Malloced] ;ESI += buffer offset retn ; Calc_Sym_Pos endp ; ; ;----------------------------------------------------------------------------- ;Link character and symbol in the dictionary ;----------------------------------------------------------------------------- Set_Char_Link proc near ; movzx ebx, [ebp+ProcFrame.Link] ; cmp edi, 0 ; EDI=Search_Table status jz short set_link ; mov [esi.TableItem.NextSym], bx ; jmp short test_sym ; ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ; set_link: ; mov [esi.TableItem.Sym], bx ;Write symbol ; test_sym: ; ;------>replaced<------ ; ; cmp bx, 1000h ; cmp bx, BITS_DEPENDED_BUFF_SIZE ;Last symbol in the dictionary? ;------>end<----------- ; jz short scl_exit ; ; call Calc_Sym_Pos ; Mark as unused (FFFF) mov word ptr [esi.TableItem.Sym], 0FFFFh mov word ptr [esi.TableItem.NextSym], 0FFFFh mov [esi.TableItem.NextChar], al inc [ebp+ProcFrame.Link] ; ; scl_exit: ; retn ; Set_Char_Link endp ; ;