;=====================================================================
; [spamMonitor] - (c) 2008 Jérôme Bruandet
;
; Sources + docs : http://spamcleaner.net/en/spammonitor/
;
;---------------------------------------------------------------------
; Detect any outgoing SMTP connection and alert user
;
; OS : Windows (XP + Vista + Windows Server 2003/2008)
; Language : Assembler
; Compiler : Borland Tasm32
;
;---------------------------------------------------------------------
;
; License : GPL (cf LICENSE.TXT)
;
;---------------------------------------------------------------------
; Revisions :
;
; - v0.10 : 1st publication.
; - v0.20 : compatibility with old XP versions (+ XP SP1)
; and Windows Server 2003 by using
; AllocateAndGetTcpExTableFromStack API.
;
;=====================================================================
.586p
locals
jumps
.model flat, STDCALL
;=====================================================================
; constants and win32 API
include spammon.w32API
include spammon.w32const
;=====================================================================
.data
AppName db "spammon",0
hInst dd 0
RunningMsg db "spamMonitor is already running !", 0
SMtitleMsg db "spamMonitor", 0
DLLname db "iphlpapi.dll", 0
DLLnotfoundMsg db "Error : cannot find [iphlpapi.dll] !"
db 13,10,"Program halted.",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 "Error : your operating system is not "
db "compatible with spamMonitor ! Please read"
db " the doc file.",13,10
db "Program halted.", 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,\
'Left/Right click'>
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.net/en/spammonitor/?sp",0
scorgURL db "http://spamcleaner.org/en/?sp",0
scnetURL db "http://spamcleaner.net/en/?sp",0
openStr db "open",0
confDelLogMsg db "Delete [c:\spammon.log] ?",0
cantDelLogMsg db "Error : cannot delete [c:\spammon.log] !", 0
noLBselectMsg db "Select the program you want to kill in "
db "the active SMTP connections listbox !", 0
cannotKillMsg db "That process cannot be killed !",0
killMsg db "The process has been killed !",0
CrashFormatMsg db "%lX",13,10,"- adress : 0x%.8lX",0
CrashMsg1 db "Argh, spamMonitor crashed !"
db " Program will halt now.",13,10,13,10
db "- error type : 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 "Time",9,9,"Program",9,9,"IP address"
db 9,"Connection",9,"PID",13,10
db 68 dup (3dh),0
winPos dd 0
GPLmsg db "This program is free software: you can "
db "redistribute it and/or modify it under the "
db "terms of the GNU General Public License as "
db "published by the Free Software Foundation, "
db "either version 3 of the License, or (at your "
db "option) any later version.",13,10,13,10
db "This program is distributed in the hope that "
db "it will be useful, but WITHOUT ANY WARRANTY; "
db "without even the implied warranty of "
db "MERCHANTABILITY or FITNESS FOR A PARTICULAR "
db "PURPOSE. See the GNU General Public License "
db "for more details.",13,10,13,10
db "You should have received a copy of the GNU "
db "General Public License along with this program. "
db "If not, see <http://www.gnu.org/licenses/>.",13,10,13,10
db "If the source code was not included with the "
db "program, it can be donwloaded at : "
db "<http://spamcleaner.net/en/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 just in case... :
push offset BetterSafeThanSorry
call SetUnhandledExceptionFilter
; only one instance :
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:
; try to find 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
; attempt to retrieve AllocateAndGetTcpExTableFromStack address
; (XP / Windows Server 2003) :
call GetProcAddress, eax, offset winOldAPIname
test eax, eax
jz isNewer
mov oldWinVer, 1
mov APIaddress, eax
; needed for the API call :
call GetProcessHeap
mov hProcess, eax
jmp API_found
isNewer:
; if error, test with GetExtendedTcpTable API (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
; allocate a large (10Kb) buffer for TcpTable :
call GlobalAlloc,GHND, 10240
mov APImemAlloc, eax
call GlobalLock,eax
mov APIptr, eax
API_found:
; allocate 1Kb to store current SMTP connections
; (cx_buffer) + 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
; SMTP connections monitoring thread :
push offset null
push 0
push 0
push offset monitorThread
push 0
push 0
call CreateThread
; open main dialogbox :
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 : fetch address and exception code
; (SEH) in EXCEPTION_RECORD structure (esp+4) in case of
; a crash and display their values in a 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 return address :
push offset endLoop
ret
BetterSafeThanSorry endp
;=====================================================================
; monitorThread : fetch active SMTP connections
monitorThread proc
next_round:
cmp oldWinVer, 1
jnz @newwin_01
; call to 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:
; call to 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
; number of active connections :
mov ecx, [esi]
test ecx, ecx ; aucune ??
je goAhead
next_cx:
push ecx ; compteur
push esi ; pointeur
; is it SMTP port 25 ? :
cmp dword ptr [esi+14h], 1900h ; dwRemotePort
jne unwanted
; get connection state :
mov eax, [esi+4] ; dwState
mov cxState, eax
; convert to ASCII string :
add eax, 12ch
call LoadStringA, hInst, eax, offset dwStateBuffer, 60
; find remote IP :
mov eax, dword ptr [esi+10h] ; dwRemoteAddr
mov remoteIP, eax
; get application PID :
mov eax, [esi+18h] ; dwProcessId
mov processID, eax
; process name :
call getProcessName
; ensure we have found a name :
cmp byte ptr [processName], 0
jne nameOK
mov ebx, offset noProcessName
mov processName, ebx
nameOK:
; text to display :
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 ; adjust stack
; check if already present in the listebox :
push offset outBuffer
push 0
push LB_FINDSTRING
push IDC_ACTIVECX
push dlgHandle
call SendDlgItemMessageA
cmp eax, -1 ; LB_ERR
; add to listbox if unknown :
je add2LB
; set position flag :
mov ebx, [cx_buffer]
mov dword ptr [ebx+eax*4], 1
; add its PID to PIDbuffer (cx_buffer+512) :
mov ecx, processID
mov [ebx+512+eax*4], ecx
inc total_found
jmp unwanted
add2LB:
; display in listbox :
push offset outBuffer
push 0
push 180h ; LB_ADDSTRING
push IDC_ACTIVECX
push dlgHandle
call SendDlgItemMessageA
; set position flag :
mov ebx, [cx_buffer]
mov dword ptr [ebx+eax*4], 1
mov ecx, processID
mov [ebx+512+eax*4], ecx
inc total_found
; log all data (+ time) :
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
; insert to the closed connections listbox :
push offset timeBuffer+2 ; bypass CR/LF
push 0
push 181h ; LB_INSERTSTRING
push IDC_INACTIVECX
push dlgHandle
call SendDlgItemMessageA
; open dialogbox if it is minimized :
cmp dlgOpen, 0
jnz dlgAlreadyOpen
call PostMessageA, dword ptr [NIData.n_hWnd], 111h, IDM_MAIN, 0
dlgAlreadyOpen:
; activate "Kill" boutton :
call GetDlgItem, dlgHandle, IDC_KILL
call EnableWindow, eax, 1
; flash + beep :
call FlashWindow,dlgHandle ,1
; sound alert ?
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
; must free allocated memory after each call
; to AllocateAndGetTcpExTableFromStack :
call HeapFree, hProcess, 0, [APIptr]
@newwin_02:
; get number on items in the listbox :
push 0
push 0
push 18bh ; LB_GETCOUNT
push IDC_ACTIVECX
push dlgHandle
call SendDlgItemMessageA
push eax
test eax, eax
jnz cleanupLB
; deactive "Kill bouton" if no connection :
call GetDlgItem, dlgHandle, IDC_KILL
call EnableWindow, eax, 0
pop eax
jmp goAhead
cleanupLB:
pop eax
cmp eax, [total_found]
jb goAhead
; clear connection buffer
; and update the 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
; go ahead ?
cmp stopThread, 1
jnz next_round
ret
monitorThread endp
;=====================================================================
; getProcessName : find a process name from its 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 ; 1st proces
test eax, eax
jnz getnext
popad
ret
getnext:
mov eax, uProcess.th32ProcessID
; is that the one we are looking for ?
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 ; next process
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 == create ?
jnz menu_open
; remove systray icon :
call Shell_NotifyIconA, NIM_DELETE, offset NIData
mov dlgOpen, 1
; dialogbox creation :
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 == "Open" ?
jnz menu_about
call Shell_NotifyIconA, NIM_DELETE, offset NIData
mov dlgOpen, 1
; display dialogbox and move it to the lower
; right corner of the screen :
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 == "About" ?
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 == "Exit" ?
jnz def_win
mov stopThread, 1 ; stop our 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
; adjust stack
retn 10h
WndProc endp
;=====================================================================
; MainDlg : main dialogbox stuff
MainDlg proc
push ebp
mov ebp, esp
cmp dword ptr [ebp+0ch], 110h ; uMsg == WM_INITDIALOG ?
jnz @wm_command
push dword ptr [ebp+8]
mov winPos, 1
call MoveDlgBox
pop dlgHandle ; fetch its handle
; and adjust stack
; initialize tabulations (active cx) :
push offset tab_act
push 3
push 192h ; LB_SETTABSTOPS
push IDC_ACTIVECX
push dlgHandle
call SendDlgItemMessageA
; initialize tabulations (inactive cx) :
push offset tab_inact
push 4
push 192h ; LB_SETTABSTOPS
push IDC_INACTIVECX
push dlgHandle
call SendDlgItemMessageA
; sound alert checkbox :
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
; erase log file :
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 == "About..." ?
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 == "Help" ?
jne @clear_eax
; run browser :
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 : "About" dialogbox
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_scnet
mov eax, offset scorgURL
@@website:
push 1
push 0
push 0
push eax
push offset openStr
push 0
call ShellExecuteA
jmp @@end_dialog
@@is_scnet:
cmp eax, IDC_SCNET
jne @@is_icon
mov eax, offset scnetURL
jmp @@website
@@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 : dialogbox positionning
; Param. : - winPos : 0 (center) ou 1 (lower right)
; - [esp+4] : dialogbox handle
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
;=====================================================================