| Welcome to The Passion Of Code Laboratory!!! | Статьи |
Поиски свободного «почтальона Печкина». Часть 3Автор: _follower/TPOC 6. Две схемы положения наблюдения.6.1 Поиск
доступных локальных SMTP – серверов.
|
|
;============================================================ .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
;============================================================ gen proc max_num:dword |
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
Здесь мы сообщаем Вам, какие творения скоро появятся
Ссылки на сайты, где можно найти больше информации
История нашей лаборатории и ее члены
|
|
У вас есть предложения по нашему сайту? Напишите сюда |
|
Любимые сайты вирмейкеров: (WASM) (RSDN) |