;=====================================================================
; [spamMonitor] - (c)2008 Jérôme Bruandet <spammon(at)spamcleaner.org>
;
; Sources + docs : http://spamcleaner.org/spammonitor
;
;---------------------------------------------------------------------
; Détecte toute connexion SMTP sortante et alerte l'utilisateur
;
; OS : Windows (XP + Vista + Windows Server 2003/2008)
; Langage : Assembleur
; Compilateur : Borland Tasm32
;
;---------------------------------------------------------------------
;
; Licence : GPL (cf LICENCE.TXT)
;
;---------------------------------------------------------------------
; Révisions :
;
; - v0.10 : 1ère publication.
; - v0.20 : compatibilité avec les premières versions de XP
; (SP1) et Windows Server 2003 en utilisant l'API
; AllocateAndGetTcpExTableFromStack.
;
;=====================================================================
.586p
locals
jumps
.model flat, STDCALL
;=====================================================================
; fichiers des constantes et APIs win32
include spammon.w32API
include spammon.w32const
;=====================================================================
.data
AppName db "spammon",0
hInst dd 0
RunningMsg db "spamMonitor est déjà lancé !", 0
SMtitleMsg db "spamMonitor", 0
DLLname db "iphlpapi.dll", 0
DLLnotfoundMsg db "Erreur : impossible de trouver [iphlpapi.dll] !"
db 13,10,"Programme terminé.",0
; XP / Windows Server 2003 :
winOldAPIname db "AllocateAndGetTcpExTableFromStack", 0
; XP SP2 / Vista / Windows Server 2003 SP1 / Windows Server 2008 :
winNewApiName db "GetExtendedTcpTable",0
APInotfoundMsg db "Erreur : votre système d'exploitation n'est pas "
db "compatible avec spamMonitor ! Merci de consulter"
db " la documentation.",13,10
db "Programme terminé.", 0
APIsizeBuffer dd 10240
APIaddress dd 0
hProcess dd 0
APIptr dd 0
memAlloc dd 0
APImemAlloc dd 0
oldWinVer db 0
hSnapshot dd ?
uProcess PROCESSENTRY32 <>
cxState dd 0
remoteIP dd 0
cx_buffer dd 0
total_found dd 0
dwStateBuffer db 60 dup (0)
wc WNDCLASS <?,offset WndProc,?,?,?,?,?,?,?,offset AppName>
CursorPos POINT <?,?>
NIData NOTIFYICONDATA <size NOTIFYICONDATA,0,'MAPS',\
NIF_ICON+NIF_TIP+NIF_MESSAGE,WM_NOTIFYICON,0,\
'Clique gauche/droit'>
hMenu dd ?
TrayIcon dd ?
Message MSG <?>
AboutDlgName db "about",0
MainDlgName db "main",0
stopThread db 0
null dd 0
dlgHandle dd 0
dlgOpen dd 0
helpURL db "http://spamcleaner.org/spammonitor",0
scorgURL db "http://spamcleaner.org",0
openStr db "open",0
confDelLogMsg db "Supprimer [c:\spammon.log] ?",0
cantDelLogMsg db "Erreur : impossible de supprimer [c:\spammon.log] !", 0
noLBselectMsg db "Sélectionnez le programme que vous souhaitez arrêter "
db "dans la liste des connexions actives !", 0
cannotKillMsg db "Ce processus ne peut pas être arrêté !",0
killMsg db "Le processus a bien été arrêté !",0
CrashFormatMsg db "%lX",13,10,"- adresse : 0x%.8lX",0
CrashMsg1 db "Argh, spamMonitor a planté !"
db " Le programme va se terminer.",13,10,13,10
db "- type d'erreur : 0x"
CrashMsg2 db 32 dup (0)
Rect RECT <>
screenX dd ?
screenY dd ?
notepad db "notepad.exe",0
logFile db "c:\spammon.log", 0
logFileHandle dd 0
logFileHeader db "Heure",9,9,"Programme",9,"Adresse IP"
db 9,"Connexion",9,"PID",13,10
db 68 dup (3dh),0
winPos dd 0
GPLmsg db "Ce programme est libre, vous pouvez "
db "le redistribuer et/ou le modifier selon les "
db "termes de la Licence Publique Générale GNU "
db "publiée par la Free Software Foundation (version"
db " 3 ou bien toute autre version ultérieure choisie"
db " par vous).",13,10,13,10,"Ce programme est "
db "distribué car potentiellement utile, mais SANS "
db "AUCUNE GARANTIE, ni explicite ni implicite,"
db " y compris les garanties de commercialisation ou "
db "d'adaptation dans un but spécifique. Reportez-vous"
db " à la Licence Publique Générale GNU pour plus "
db "de détails.",13,10,13,10
db "Vous devez avoir reçu une copie de la Licence "
db "Publique Générale GNU en même temps que ce "
db "programme ; si ce n'est pas le cas, consultez "
db "<http://www.gnu.org/licenses/>.",13,10,13,10
db "Si le code source n'était pas inclus avec ce "
db "programme, il est téléchargeable à l'adresse : "
db "<http://spamcleaner.org/spammonitor/>.",0
soundAlert db "ALERT",0
ee dd 0
ee_buffer db 100 dup (0)
bWritten dd 0
processID dd 0
PIDbuffer dd 0
processName dd 0
noProcessName db "??????????",0
tab_act dd 20*4
dd 35*4
dd 250
tab_inact dd 11*4
dd 35*4
dd 250
dd 350
timeFormat db 13,10,"hh:mm:ss",9,0
stringFormat db '%s',9,'%i.%i.%i.%i',9,'[%hS]',9,'%i',0
timeBuffer db 11 dup (0)
outBuffer db 100 dup (0)
;=====================================================================
.code
Main proc
; SEH au cas ou... :
push offset BetterSafeThanSorry
call SetUnhandledExceptionFilter
; on n'autorise qu'une seule instance du programme :
call CreateMutexA, 0, 0, offset AppName
mov hInst, eax
call GetLastError
cmp eax, 183 ; ERROR_ALREADY_EXISTS
jne not_running
call CloseHandle, hInst
push 10h
push offset SMtitleMsg
push offset RunningMsg
push 0
call MessageBoxA
jmp quit
not_running:
; vérifie si on trouve iphlpapi.dll :
call LoadLibraryA, offset DLLname
test eax, eax
jnz DLL_found
push 10h
push offset SMtitleMsg
push offset DLLnotfoundMsg
push 0
call MessageBoxA
jmp quit
DLL_found:
mov null, eax
; tente de récupérer l'adresse AllocateAndGetTcpExTableFromStack
; (XP / Windows Server 2003) :
call GetProcAddress, eax, offset winOldAPIname
test eax, eax
jz isNewer
mov oldWinVer, 1
mov APIaddress, eax
; nécessaire pour l'appel à l'API :
call GetProcessHeap
mov hProcess, eax
jmp API_found
isNewer:
; si erreur, on test avec GetExtendedTcpTable (XP SP2 / Vista /
; Windows Server 2003 SP1 / Windows Server 2008) :
call GetProcAddress, null, offset winNewApiName
test eax, eax
jnz isNewer2
push 10h
push offset SMtitleMsg
push offset APInotfoundMsg
push 0
call MessageBoxA
jmp quit
isNewer2:
mov APIaddress, eax
; alloue un large (10Ko) buffer pour TcpTable :
call GlobalAlloc,GHND, 10240
mov APImemAlloc, eax
call GlobalLock,eax
mov APIptr, eax
API_found:
; alloue 1Ko pour y stocker les connexions SMTP en cours
; (cx_buffer) et les PIDs (PIDbuffer) :
call GlobalAlloc,GHND, 1024
mov memAlloc, eax
call GlobalLock,eax
mov cx_buffer, eax
add eax, 512
mov PIDbuffer, eax
call GetModuleHandleA, 0
mov hInst, eax
mov wc.w_hInstance, eax
call LoadMenuA, hInst, 103 ; menu
mov hMenu, eax
call LoadIconA, hInst, 101 ; icone
mov TrayIcon, eax
mov NIData.n_hIcon, eax
mov wc.w_hIcon, eax
call RegisterClassA, offset wc
push 0
push hInst
push 0
push 0
push 0
push 0
push 0
push 0
push 0
push 0
push offset AppName
push 0
call CreateWindowExA
mov NIData.n_hWnd, eax
; thread de surveillance des connexions SMTP :
push offset null
push 0
push 0
push offset monitorThread
push 0
push 0
call CreateThread
; ouverture de la boite de dialogue :
push 0
push IDM_CREATE
push 111h
push dword ptr [NIData.n_hWnd]
call PostMessageA
push 0
push 80h
push 2
push 0
push 1
push 40000000h
push offset logFile
call CreateFileA
mov logFileHandle, eax
call lstrlenA, offset logFileHeader
push 0
push offset bWritten
push eax
push offset logFileHeader
push logFileHandle
call WriteFile
messageLoop:
call GetMessageA, offset Message, 0, 0, 0
or eax, eax
jz endLoop
call TranslateMessage, offset Message
call DispatchMessageA, offset Message
jmp messageLoop
endLoop:
call Shell_NotifyIconA, NIM_DELETE, offset NIData
cmp oldWinVer, 1
jz noneed2free
call GlobalUnlock, [APImemAlloc]
call GlobalFree, [APImemAlloc]
noneed2free:
call GlobalUnlock, [memAlloc]
call GlobalFree, [memAlloc]
call CloseHandle, logFileHandle
quit:
call ExitProcess, 0
Main endp
;=====================================================================
; BetterSafeThanSorry : récupère l'adresse et le code de l'exception
; (SEH) dans la structure EXCEPTION_RECORD (esp+4) en cas de
; plantage et affiche leurs valeurs dans une messagebox.
BetterSafeThanSorry proc
mov esi, dword ptr [esp+4]
mov esi, dword ptr [esi]
mov eax, dword ptr [esi+12]
push eax
mov eax, dword ptr [esi]
push eax
push offset CrashFormatMsg
push offset CrashMsg2
call _wsprintfA
add esp, 4*4
push 40h
push offset SMtitleMsg
push offset CrashMsg1
push 0
call MessageBoxA
mov stopThread, 1
; force l'adresse de retour
push offset endLoop
ret
BetterSafeThanSorry endp
;=====================================================================
; monitorThread : récupère les connexions SMTP actives
monitorThread proc
next_round:
cmp oldWinVer, 1
jnz @newwin_01
; appel de AllocateAndGetTcpExTableFromStack :
push 2 ; AF_INET
push 0 ; dwFlags
push hProcess ; hHeap
push 0 ; unsorted
push offset APIptr ; ppTcpTable
call dword ptr [APIaddress]
test eax, eax ; ERROR_SUCCESS (0) ?
je APIok
jmp goAhead
@newwin_01:
; appel de GetExtendedTcpTable :
push 0 ; Reserved
push 5 ; TCP_TABLE_OWNER_PID_ALL
push 2 ; AF_INET
push 0 ; unsorted
push offset APIsizeBuffer ; pdwSize
push [APIptr] ; pTcpTable
call dword ptr [APIaddress]
cmp eax, 122 ; ERROR_INSUFFICIENT_BUFFER
je goAhead
APIok:
mov esi, [APIptr] ; pointe sur la structure
test esi, esi
je goAhead
; nombre de connexions actives :
mov ecx, [esi]
test ecx, ecx ; aucune ??
je goAhead
next_cx:
push ecx ; compteur
push esi ; pointeur
; verifie si le port nous interesse (25) :
cmp dword ptr [esi+14h], 1900h ; dwRemotePort
jne unwanted
; recupere l'etat de la connexion :
mov eax, [esi+4] ; dwState
mov cxState, eax
; conversion en chaine ASCII :
add eax, 12ch
call LoadStringA, hInst, eax, offset dwStateBuffer, 60
; recupere l'IP de la connexion :
mov eax, dword ptr [esi+10h] ; dwRemoteAddr
mov remoteIP, eax
; recupere le PID :
mov eax, [esi+18h] ; dwProcessId
; ; on ne garde pas les PIDs égal à 0 ([System Process]) :
; test eax, eax
; jz unwanted
mov processID, eax
; récupère le nom du processus:
call getProcessName
; verifie qu'on a bien un nom :
cmp byte ptr [processName], 0
jne nameOK
mov ebx, offset noProcessName
mov processName, ebx
nameOK:
; prepare le texte a afficher :
push processID
push offset dwStateBuffer
mov ebx, remoteIP
movzx ebx, byte ptr [remoteIP+3]
push ebx
movzx ebx, byte ptr [remoteIP+2]
push ebx
movzx ebx, byte ptr [remoteIP+1]
push ebx
movzx ebx, byte ptr [remoteIP]
push ebx
push processName
push offset stringFormat
push offset outBuffer
call _wsprintfA
add esp, 4*9 ; réajuste la pile
; recherche si déjà present dans la listebox :
push offset outBuffer
push 0
push LB_FINDSTRING
push IDC_ACTIVECX
push dlgHandle
call SendDlgItemMessageA
cmp eax, -1 ; LB_ERR
; si inconnu, ajoute dans listbox
je add2LB
; active le flag de positionnement :
mov ebx, [cx_buffer]
mov dword ptr [ebx+eax*4], 1
; ajoute le PID dans PIDbuffer (cx_buffer+512) :
mov ecx, processID
mov [ebx+512+eax*4], ecx
inc total_found
jmp unwanted
add2LB:
; on affiche dans la listbox :
push offset outBuffer
push 0
push 180h ; LB_ADDSTRING
push IDC_ACTIVECX
push dlgHandle
call SendDlgItemMessageA
; active le flag de positionnement :
mov ebx, [cx_buffer]
mov dword ptr [ebx+eax*4], 1
mov ecx, processID
mov [ebx+512+eax*4], ecx
inc total_found
; rajoute les infos au fichier log (+ heure) :
push 11
push offset timeBuffer
push offset timeFormat
push 0
push 8
push 0
call GetTimeFormatA
push 0
push offset bWritten
push 11
push offset timeBuffer
push logFileHandle
call WriteFile
call lstrlenA, offset outBuffer
push 0
push offset bWritten
push eax
push offset outBuffer
push logFileHandle
call WriteFile
; insertion dans la listbox des anciennes connexions :
push offset timeBuffer+2 ; passe outre le CR/LF
push 0
push 181h ; LB_INSERTSTRING
push IDC_INACTIVECX
push dlgHandle
call SendDlgItemMessageA
; ouvre la dialogbox si elle est minimisée :
cmp dlgOpen, 0
jnz dlgAlreadyOpen
call PostMessageA, dword ptr [NIData.n_hWnd], 111h, IDM_MAIN, 0
dlgAlreadyOpen:
; active le boutton "Kill" :
call GetDlgItem, dlgHandle, IDC_KILL
call EnableWindow, eax, 1
; flash + beep :
call FlashWindow,dlgHandle ,1
; alerte sonore ?
call IsDlgButtonChecked, dlgHandle, IDC_ALERTE
test eax, eax
jz noWave
call PlaySound, offset soundAlert, hInst, 42004h
jmp unwanted
noWave:
call MessageBeep, 40h
unwanted:
pop esi
pop ecx
dec ecx
jcxz noMoreCX
add esi, 18h
jmp next_cx
noMoreCX:
cmp oldWinVer, 1
jnz @newwin_02
; libère la mémoire après chaque appel
; à AllocateAndGetTcpExTableFromStack :
call HeapFree, hProcess, 0, [APIptr]
@newwin_02:
; récupère le nombre d'éléments dans listbox :
push 0
push 0
push 18bh ; LB_GETCOUNT
push IDC_ACTIVECX
push dlgHandle
call SendDlgItemMessageA
push eax
test eax, eax
jnz cleanupLB
; desative le bouton "Kill" si aucune connexion :
call GetDlgItem, dlgHandle, IDC_KILL
call EnableWindow, eax, 0
pop eax
jmp goAhead
cleanupLB:
pop eax
cmp eax, [total_found]
jb goAhead
; supprime les connexions du buffer
; et réactualise la listbox :
mov ebx, [cx_buffer]
@cleanup_loop:
dec eax ; zero-based
cmp eax, -1
je goAhead
cmp dword ptr [ebx+eax*4], 1
jz resetFlag
push eax
push 0
push eax
push 182h ; LB_DELETESTRING
push IDC_ACTIVECX
push dlgHandle
call SendDlgItemMessageA
pop eax
resetFlag:
mov dword ptr [ebx+eax*4], 0
jmp @cleanup_loop
goAhead:
mov dword ptr [total_found], 0
call Sleep, 150
; on continue ?
cmp stopThread, 1
jnz next_round
ret
monitorThread endp
;=====================================================================
; getProcessName : récupère le nom du processus à partir de son PID
; Param. : processID == PID
getProcessName proc
pushad
mov processName, 0
call CreateToolhelp32Snapshot, 2, 0 ; snapshot
mov [hSnapshot], eax
mov [uProcess.dwSize], size PROCESSENTRY32
push offset uProcess
push eax
call Process32First ; 1er processus
test eax, eax
jnz getnext
popad
ret
getnext:
mov eax, uProcess.th32ProcessID
; est-ce le notre?
cmp eax, dword ptr [processID]
jnz unknown
mov eax, offset uProcess.szExeFile
mov processName, eax
jmp closeSnapshot
unknown:
push offset uProcess
push [hSnapshot]
call Process32Next ; processus suivants
test eax, eax
jnz getnext
closeSnapshot:
push [hSnapshot]
call CloseHandle
popad
ret
getProcessName endp
;=====================================================================
; WndProc
; Param. : hWnd, uMsg, wParam et lParam
WndProc proc
enter 0, 0
push ebx
push esi
push edi
wm_destroy:
cmp dword ptr [ebp+0ch], 2 ; uMsg == WM_DESTROY ?
jnz wm_command
call PostQuitMessage, 0
jmp clear_eax
wm_command:
cmp dword ptr [ebp+0ch], 111h ; uMsg == WM_COMMAND ?
jnz wm_notify
create_dlg:
cmp word ptr [ebp+10h], IDM_CREATE ; wParam == creation ?
jnz menu_open
; supprime l'icone de la systray
call Shell_NotifyIconA, NIM_DELETE, offset NIData
mov dlgOpen, 1
; création de la boite de dialogue
push 0
push offset MainDlg
push dword ptr [ebp+8]
push offset MainDlgName
push hInst
call DialogBoxParamA
jmp clear_eax
menu_open:
cmp word ptr [ebp+10h], IDM_MAIN ; wParam == "Ouvrir" ?
jnz menu_about
call Shell_NotifyIconA, NIM_DELETE, offset NIData
mov dlgOpen, 1
; affiche et positionne la boite de dialogue
; en bas a droite :
mov winPos, 1
push dlgHandle
call MoveDlgBox
add esp, 4
call ShowWindow, dlgHandle, 9 ; SW_RESTORE
jmp clear_eax
menu_about:
cmp word ptr [ebp+10h], IDM_ABOUT ; wParam == "A propos" ?
jnz menu_exit
push 0
push offset AboutDlg
push dword ptr [ebp+8]
push offset AboutDlgName
push hInst
call DialogBoxParamA
jmp clear_eax
menu_exit:
cmp word ptr [ebp+10h], IDM_EXIT ; wParam == "Quitter" ?
jnz def_win
mov stopThread, 1 ; arrete notre thread
push dword ptr [ebp+8]
call DestroyWindow
jmp clear_eax
wm_notify:
cmp dword ptr [ebp+0ch], 400h ; uMsg == WM_USER ?
jnz def_win
cmp dword ptr [ebp+14h], 205h ; lParam == WM_RBUTTONUP ?
jz show_menu
cmp dword ptr [ebp+14h], 202h ; lParam == WM_LBUTTONUP ?
jnz def_win
show_menu:
call GetCursorPos , offset CursorPos
xor ecx, ecx
setnz cl
call GetSubMenu, hMenu, ecx
push eax
push dword ptr[ebp+8]
call SetForegroundWindow
pop eax
push 0
push dword ptr [ebp+8]
push 0
push CursorPos.y
push CursorPos.x
push TPM_RIGHTBUTTON
push eax
call TrackPopupMenu
call PostMessageA, dword ptr [ebp+08h], 0, 0, 0
jmp clear_eax
def_win:
push dword ptr [ebp+14h] ; lParam
push dword ptr [ebp+10h] ; wParam
push dword ptr [ebp+0ch] ; uMsg
push dword ptr [ebp+8] ; hWnd
call DefWindowProcA
jmp Return
clear_eax:
xor eax, eax
Return:
pop edi
pop esi
pop ebx
leave
; réajuste la pile
retn 10h
WndProc endp
;=====================================================================
; MainDlg : gestion de la boite de dialogue principale
MainDlg proc
push ebp
mov ebp, esp
cmp dword ptr [ebp+0ch], 110h ; uMsg == WM_INITDIALOG ?
jnz @wm_command
; positionne la boite de dialogue en bas a droite :
push dword ptr [ebp+8]
mov winPos, 1
call MoveDlgBox
pop dlgHandle ; recupere son handle
; et réajuste la pile
; initialise les tabulations :
push offset tab_act
push 3
push 192h ; LB_SETTABSTOPS
push IDC_ACTIVECX
push dlgHandle
call SendDlgItemMessageA
; initialise les tabulations :
push offset tab_inact
push 4
push 192h ; LB_SETTABSTOPS
push IDC_INACTIVECX
push dlgHandle
call SendDlgItemMessageA
; checkbox alerte sonore :
call CheckDlgButton, dlgHandle, IDC_ALERTE, 1
mov eax, 1
leave
retn 10h
@wm_command:
cmp dword ptr [ebp+0ch], 111h ; uMsg == WM_COMMAND
jne @clear_eax
@idc_ok:
mov eax, dword ptr [ebp+10h]
and eax, 0000FFFFh
cmp eax, IDC_OK ; wParam == "OK" ?
jne @idc_kill
call ShowWindow, dlgHandle, 0 ; SW_HIDE
call Shell_NotifyIconA, NIM_ADD, offset NIData
mov dlgOpen, 0
jmp @clear_eax
@idc_kill:
cmp eax, 1005 ; wParam == "Kill !" ?
jne @idc_viewlog
push 0
push 0
push 188h ; LB_GETCURSEL
push IDC_ACTIVECX
push dlgHandle
call SendDlgItemMessageA
cmp eax, -1 ; LB_ERR
jne fetchLBtext
push 30h
push offset SMtitleMsg
push offset noLBselectMsg
push dlgHandle
call MessageBoxA
jmp @clear_eax
fetchLBtext:
mov ebx, [PIDbuffer]
mov ebx, [ebx+eax*4]
test ebx, ebx
jnz @kill_it
@cannotKill:
push 10h
push offset SMtitleMsg
push offset cannotKillMsg
push dlgHandle
call MessageBoxA
jmp @clear_eax
@kill_it:
push ebx
push 1
push 1 ; PROCESS_TERMINATE
call OpenProcess
test eax, eax
jz @cannotKill
push 0
push eax
call TerminateProcess
test eax, eax
jz @cannotKill
push 40h
push offset SMtitleMsg
push offset killMsg
push dlgHandle
call MessageBoxA
jmp @clear_eax
@idc_viewlog:
cmp eax, IDC_VIEWLOG ; wParam == "Voir Log" ?
jne @idc_dellog
push 1
push 0
push 0
push offset logFile
push offset openStr
push offset notepad
call ShellExecuteA
jmp @clear_eax
@idc_dellog:
cmp eax, IDC_DELLOG ; wParam == "Effacer Log" ?
jne @idc_about
; efface le fichier log :
push 31h
push offset SMtitleMsg
push offset confDelLogMsg
push dlgHandle
call MessageBoxA
cmp eax, 1
jnz @clear_eax
call CloseHandle, logFileHandle
push 0
push 80h
push 2
push 0
push 1
push 40000000h
push offset logFile
call CreateFileA
mov logFileHandle, eax
call lstrlenA, offset logFileHeader
push 0
push offset bWritten
push eax
push offset logFileHeader
push logFileHandle
call WriteFile
cmp bWritten, 0
jnz @clear_eax
push 10h
push offset SMtitleMsg
push offset cantDelLogMsg
push dlgHandle
call MessageBoxA
jmp @clear_eax
@idc_about:
cmp eax, IDC_ABOUT ; wParam == "A Propos.." ?
jne @idc_help
push 0
push offset AboutDlg
push dword ptr [ebp+8]
push offset AboutDlgName
push hInst
call DialogBoxParamA
jmp @clear_eax
@idc_help:
cmp eax, IDC_HELP ; wParam == "Aide" ?
jne @clear_eax
; lance le navigateur :
push 1
push 0
push 0
push offset helpURL
push offset openStr
push 0
call ShellExecuteA
@clear_eax:
xor eax, eax
leave
retn 10h
MainDlg endp
;=====================================================================
; AboutDlg : gestion de la boite de dialoque 'A propos'
AboutDlg Proc
push ebp
mov ebp, esp
@@wm_initdialog:
cmp dword ptr [ebp+0ch], 110h ; WM_INITDIALOG
jnz @@wm_command
push dword ptr [ebp+8]
mov winPos, 0
call MoveDlgBox
add esp, 4
push offset GPLmsg
push IDC_GLP
push dword ptr [ebp+08h]
call SetDlgItemTextA
mov eax, 1
leave
retn 10h
@@wm_command:
cmp dword ptr [ebp+0ch], 111h ; WM_COMMAND
jne @@wm_notify
mov eax, dword ptr [ebp+10h]
and eax, 0000FFFFh
cmp eax, IDC_OK
jne @@idc_scorg
@@end_dialog:
call Shell_NotifyIconA, NIM_ADD, offset NIData
call EndDialog, dword ptr [ebp+08h], 0
mov eax, 1
leave
retn 10h
@@idc_scorg:
cmp eax, IDC_SCORG
jne @@is_icon
push 1
push 0
push 0
push offset scorgURL
push offset openStr
push 0
call ShellExecuteA
jmp @@end_dialog
@@is_icon:
cmp eax, 2121
jne @@clear_eax
cmp word ptr [ebp+12h], 1
jne @@clear_eax
cmp dword ptr [ee], 4
jb @@clear_eax
mov stopThread, 1
call PostMessageA, dword ptr [NIData.n_hWnd], 111h, IDM_EXIT, 0
jmp @@end_dialog
@@wm_notify:
cmp dword ptr [ebp+0ch], 206h
jne @@clear_eax
cmp word ptr [ebp+10h], 0ah
jne @@clear_eax
@@easter_egg_inside:
inc dword ptr [ee]
cmp dword ptr [ee], 1
jb @@clear_eax
cmp dword ptr [ee], 4
je ee_thread
cmp dword ptr [ee], 3
ja @@clear_eax
push 40h
push offset SMtitleMsg
mov eax, [ee]
add eax, 989
call LoadStringA, hInst, eax, offset ee_buffer, 100
push offset ee_buffer
push dword ptr [ebp+8]
call MessageBoxA
jmp @@clear_eax
ee_thread:
mov stopThread, 1
call Sleep, 250
call EnableMenuItem, hMenu, IDM_EXIT, 1
mov ecx, 6
@@ee_nextbtn:
mov eax, ecx
add eax, 949
mov ebx, ecx
add ebx, 999
push ecx
call LoadStringA, hInst, eax, offset ee_buffer, 100
call SetDlgItemTextA, dlgHandle, ebx, offset ee_buffer
pop ecx
loop @@ee_nextbtn
mov stopThread, 0
call CreateThread, 0, 0, offset eeThread, 0, 0, offset null
jmp @@end_dialog
@@clear_eax:
xor eax, eax
leave
retn 10h
AboutDlg endp
eeThread proc
@@next_ee:
cmp dlgOpen, 1
je @@ee_open
call PostMessageA, dword ptr [NIData.n_hWnd], 111h, IDM_MAIN, 0
mov dlgOpen, 1
@@ee_open:
call SendDlgItemMessageA, dlgHandle, 1007, 184h, 0, 0
mov ecx, 0fh
mov ebx, ecx
add ebx, 900
@@ee_nextitm:
push ecx
call LoadStringA, hInst, ebx, offset ee_buffer, 100
call GetTickCount
and eax, 0fh
push offset ee_buffer
push 0
cmp al, 8
jb @@ins
push 180h
jmp @@add
@@ins:
push 181h
@@add:
push IDC_ACTIVECX
push dlgHandle
call SendDlgItemMessageA
pop ecx
dec ebx
loop @@ee_nextitm
call PlaySound, offset soundAlert, hInst, 42004h
call Sleep, 100
call FlashWindow, dlgHandle, 1
cmp stopThread, 1
jnz @@next_ee
ret
eeThread endp
;=====================================================================
; MoveDlgBox : positionne une boite de dialogue au centre
; ou en bas à droite de l'écran.
; Param. : - winPos : 0 (centre) ou 1 (bas à droite)
; - [esp+4] : handle dialogbox
MoveDlgBox proc
push offset Rect
push dword ptr [esp+8]
call GetWindowRect
call GetSystemMetrics, 16 ; SM_CXFULLSCREEN
mov esi, eax
cmp winPos, 0
jnz @1
shr esi, 1
jmp @2
@1:
sub esi, 10
@2:
mov eax, Rect.right
sub eax, Rect.left
cmp winPos, 0
jnz @3
shr eax, 1
@3:
sub esi, eax
call GetSystemMetrics, 17 ; SM_CYFULLSCREEN
cmp winPos, 0
jnz @4
shr eax, 1
jmp @5
@4:
add eax, 10
@5:
mov ecx, Rect.bottom
sub ecx, Rect.top
cmp winPos, 0
jnz @6
shr ecx, 1
@6:
sub eax, ecx
push 0
mov ebx, Rect.bottom
sub ebx, Rect.top
push ebx
mov ebx, Rect.right
sub ebx, Rect.left
push ebx
push eax
push esi
push dword ptr [esp+18h]
call MoveWindow
ret
MoveDlgBox endp
;=====================================================================
End Main
;=====================================================================