Отправка по SMTP с авторизацией

Дата публикации 30 апр 2006

Отправка по SMTP с авторизацией — Архив WASM.RU

  1. Введение.
  2. SMTP. Теория
  3. SMTP. Практика
  4. Заключение

1. Введение.

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

В этой статье я попытаюсь раскрыть эту проблему, простыми словами написать то, что написано в более "расплывчатом" виде в rfc, который почему-то всем лень читать. И, конечно, данная статья будет ориентирована на "низкоуровневых" программистов. Я буду писать под фасм, но думаю, что для Вас не составит особого труда переделать примеры под более удобный для Вас компилятор.

2. SMTP. Теория

Итак, теперь кратко, что такое SMTP - Simple Mail Transfer Protocol. Задача протокола - это удобная передача электронной почты. Но если не делать отступлений и не вдаваться в подробности, то это просто некоторое количество команд и "спецсимволов", позволяющих отправлять письма. Для того, чтоб собственноручно пообщаться с сервером, можно взять обычный телнет (Пуск-Выполнить-telnet) и зайти на 25 порт сервера.

Делается это командой open smtp.servak.net 25. И ,если всё пройдёт удачно, Вы получите ответ от сервера.

Далее следует начать работу с сервером, а для этого его надо поприветствовать. так как сервер нормальных слов не понимает, сделать это надо командой EHLO someword[CRLF].

[CRLF]=Enter=13,10 (каждая команда завершается этой последовательностью байт). После утвердительного ответа можно приступать непосредственно к отправке писем.

Задать отправителя письма можно командой MAIL FROM:<e-mail@server.ext>[CRLF], а получателя RCPT TO:<e-mail@server.ext>[CRLF].

После того как эти параметры заданы, можно приступать к написанию письма. Для этого надо послать команду DATA[CRLF]. Теперь то можно набрать тело письма. Чтоб завершить письмо, следует отправить последовательность вида [CRLF].[CRLF] на сервер. Если все пройдёт удачно, то письмо будет отправлено адресату. Завершить работу с сервером следует командой QUIT[CRLF].

Так просто было общаться с сервером не слишком долгое время. Теперь, прежде чем отправить письмо, следует авторизироваться. Есть несколько способов авторизации, но я опишу самый простой, который поддерживается большинством SMTP-серверов. Чтоб начать авторизацию, следует послать на сервер команду AUTH LOGIN[CRLF], но прежде убедитесь, что данный сервер поддерживает эту команду.

В случае принятия команды сервер запросит у Вас логин и пароль (запросы будут зашифрованы в Base64). следовательно логин и пароль надо отправлять, предварительно зашифровав их в Base64. При удачной аутентификации будет выведено соответствующее сообщение. После этого Вы можете задать адрес отправителя (должен быть привязан к логину), получателя и отправить письмо.

Но лучше раз увидеть, чем 100 раз услышать, поэтому я приведу пример диалога с сервером (s - server, u - user):

Код (Text):
  1.  
  2. s:220 mail.ru ESMTP Sat, 15 Apr 2006 16:46:49 +0400
  3. u:EHLO server
  4. s:250-mx6.mail.ru Hello server [111.11.11.111]
  5. s:250-SIZE 10485760
  6. s:250-8BITMIME
  7. s:250-AUTH PLAIN LOGIN
  8. s:250 PIPELINING
  9. u:AUTH LOGIN
  10. s:334 VXNlcm5hbWu6
  11. u:dGVzdF9fXzAwMDAz
  12. s:334 UGFzc3dvcmQ6
  13. u:dGVzdF9fXzAwMDAz
  14. s:235 Authentication succeeded
  15. u:MAIL FROM:<test___00003@mail.ru>
  16. s:250 OK
  17. u:RCPT TO:<test___00003@mail.ru>
  18. s:250 Accepted
  19. u:DATA
  20. s:354 Enter message, ending with "." on a line by itself
  21. u:asdf
  22. u:.
  23. s:250 OK id=1FUkCk-000OR2-00
  24. u:QUIT
  25. s:221 mx6.mail.ru closing connection

3. SMTP. Практика.

Приступим непосредственно к практике. Напишем небольшую программку, которая будет посылать небольшое сообщение на заданный почтовый ящик с авторизацией. Я предполагаю, что Вы уже знакомы с WinSocks, и не буду на этом останавливаться. Вы можете скачать полную версию программы, а я разъясню только ключевые моменты. А именно работу процедуры Send_Mail

proc Send_Mail pszmess,pszfrom,pszto,pszlog,pszpass,pszserv,pszsubj

pszMess - само сообщение.
pszfrom - адрес отправителя
pszto - адрес получателя
pszlog, szpass - логин и пароль для авторизации
pszserv - сервер
pszsubj - тема письма

Код (Text):
  1.  
  2. lea ebx,[base64log]
  3. invoke lstrlen,[pszlog]
  4. stdcall Base64Encode, dword [pszlog],ebx,eax
  5. add ebx,200
  6. invoke lstrlen,[pszpass]
  7. stdcall Base64Encode, dword [pszpass],ebx,eax

Тут шифруется логин и пароль в Base64, используется алгоритм by RT Fishel без использования алфавита. Далее идёт работа с WinSocks

Код (Text):
  1.  
  2.         invoke     socket,2,1,0

Создается сокет

Код (Text):
  1.  
  2.         invoke     gethostbyname,[pszserv]
  3.         test eax,eax
  4.         jz cantfinds
  5.         mov        eax,[eax+0ch]
  6.         mov        eax,[eax]
  7.         mov        eax,[eax]

Тут в качестве параметра gethostbyname передаётся указатель на строку с именем сервера, а потом из структуры hostent извлекается sin_addr.

Код (Text):
  1.  
  2. mov ax,25
  3. xchg ah,al
  4. mov      word [saddr.sin_port], ax

Коннект на 25 порт, только нужно учитывать порядок байт.

Код (Text):
  1.  
  2. call       get_data
  3. test       eax,eax
  4. jz         errrecv

После коннекта прочитаем ответ сервера.

Следует отметить, что все ответы сервера начинаются с определенного кода. Несложно увидеть, что в случае успеха код начинается либо с цифры 2, либо с 3. На этом основана проверка ошибок в процедуре get_data.

Теперь немного о вспомогательных процедурах:

sendNrecv - передаёт строку, указатель на которую следует поместить в еах, на сервер, получает ответ сервера.
Send_String - просто передает строку, адрес которой передан как параметр, на сервер.

Я не считаю, что следует рассматривать работу каждой из них, если Вы знакомы с WinSocks, то без проблем сделаете это сами.

Код (Text):
  1.  
  2.         lea eax,[base64log]
  3.         stdcall Send_String,eax
  4.         mov eax,szEnd+3
  5.         call       sendNrecv
  6.  
  7.         lea eax,[base64pass]
  8.         stdcall Send_String,eax
  9.         mov eax,szEnd+3
  10.         call       sendNrecv

Отсылка логина и пароля на сервер. szEnd+3 - указатель на [CRLF]. Получается, что мы передаем строку, а после этого [CRLF] и читаем ответ. Далее все по порядку, описанному в начале статьи.

Программа отсылает строки примерно таким образом:

Код (Text):
  1.  
  2. MAIL FROM:<
  3. adres@mail.ru
  4. >[CRLF]
  5. [читаем ответ]
  6.  
  7. RCPT TO:<
  8. adres@mail.ru
  9. >[CRLF]
  10. [читаем ответ]
  11.  
  12. DATA[CRLF]
  13. Subject:
  14. SMTP work's
  15. [CRLF]
  16.  
  17. test
  18. [CRLF].[CRLF]
  19. [читаем ответ]
  20.  
  21. QUIT
  22. [ответ]
s

Чтоб передать файл, нужно в теле сообщения создать заголовок вида

Код (Text):
  1.  
  2. Content-Type: application/octet-stream; name="file.bin"
  3. Content-Disposition: attachment; filename="file.bin"
  4. Content-Transfer-Encoding: base64

После чего просто передать файл, зашифрованный в Base64.

4. Заключение

Думаю, что эта статья хоть кому-нибудь пригодится. Или хотя бы облегчит жизнь, так как готовой информации для "низкоуровнего" программиста достаточно мало, а искать в интернете крохи информации и исходники, а потом в них разбираться порой нет времени, а иногда и желания.

Благодарность:

  1. Ct757 за помощь и утилиту pfcode, которая придала моему ужасному коду ровный и красивый вид.
  2. Bill Prisoner за идею написания статьи.
  3. revers я б вообще не трогал этот СМТП.

Использованная литература:

  1. Использование сокетов/взаимодействие с SMTP-сеpвеpами [Billy Belcebu/IKX, пер. Aquila]
  2. Руководство Beej по сетевому программированию, используя интернет-сокеты [Брайан "Beej" Холл, пер. varnie]
  3. INFECTED VOICE #15 - Введение ... в Интернет. Диалог с SMTP сервером на Assembler
  4. Исходный код Xinch.
  5. RFC #821 #2554

Программа smtp.rar © Freeman


0 2.088
archive

archive
New Member

Регистрация:
27 фев 2017
Публикаций:
532