TraceRoute на FASM

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by slesh, 23 Jun 2007.

  1. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    Вот както писал для себя маленькую прогу на FASM.
    Прога предназначенна для трассировки прохождения данных между серверами. Почти аналог стандартной виндовой, за одним исключением:
    1) Не показывает время прохождения пакетов
    2) Имеет графический интерфейс
    3) после компила прога весит 4 кила.

    Вот хорошо откоментированный исходник:
    От туда можно взять функцию пингования сервера и работу с диалогами. Раньше там был еще и XP манифест, чтобы красиво выглядело все, но я его потом убрал (т.к. программа от него слегка жирноватая становится :) )
    Компилить как всегда через стандартный FASM
    Code:
    format PE GUI 4.0
    entry _start
    include 'd:\coding\fasm\include\win32ax.inc'
    include 'd:\coding\fasm\include\encoding\win1251.inc'
    
    section '.code' code readable writable executable
    _start:
    jmp realstart  ; переход на начало кода
    
     ; необходимые структуры
    struct IP_OPTION_INFORMATION
      Ttl db 0
      Tos db 0
      Flags db 0
      OptionsSize db 0
      OptionsData dd 0
    ends
    
    
    struct ICMP_ECHO_REPLY
     Address dd 0
     Status dd 0
     RoundTripTime dd 0
     DataSize  dw 0
     Reserved  dw 0
     Data dd 0
     Options IP_OPTION_INFORMATION
     PingBuf db 32 dup (0)
    ends
    
    struct TInAddr
     b1 db 0
     b2 db 0
     b3 db 0
     b4 db 0
    ends
    
    hwnd_g dd 0  ; дискриптор окна
    memo_buf dd 0  ; буфер в котором хранится отображаемый в мемо текст
    Optionss IP_OPTION_INFORMATION
    InAddr TInAddr
    Reply ICMP_ECHO_REPLY
    PingBuf db 32 dup (0)
    IP_BUF db 256 dup (0)  ; буфер для IP адреса или DNS
    REMOTE_IP db 16 dup (0)  ; удаленный IP
    handle dd 0
    WSData WSADATA	; для работы с сокетами
    SOCKADDR sockaddr_in  ; для работы с сокетами
    HostEnt hostent  ; для определения IP<-->DNS
    small_buf dd 0	; малый (временный) буфер
    num_buf db 10 dup (0)  ; буфер для числа
    schet dd 0  ; счетчик серверов
    hwndg dd 0  ; дискриптор окна
    formats db "%d",0  ; формат приобразования числа в строку
    crlf db 13,10,0 ; для перехода на слудующую строку в мемо
    realstart:  ; начало проги
    invoke GetProcessHeap ; получаем адрес кучи процесса
    invoke HeapAlloc,eax,0,65535 ; выделяем 65 килобайт в куче под буфер для мемо
    mov [memo_buf],eax  ; сохраняем адрес памяти буфера
    mov [eax],dword 0
    invoke GetProcessHeap ; получаем адрес кучи процесса
    invoke HeapAlloc,eax,0,10240 ; выделяем малый буфер
    mov [small_buf],eax  ; сохраняем адрес памяти буфера
    mov [eax],dword 0
    invoke GetModuleHandle,0  ; получение дискриптора
    invoke DialogBoxParam,eax,100,HWND_DESKTOP,MainProc,0  ; вызвать диалог
    
    proc Ping InetAddress,ttl  ; пингование передается адрес сервера и ТТЛ
    invoke IcmpCreateFile  ;
    cmp eax,INVALID_HANDLE_VALUE  ; если не удалось создать "ICMP файл"
    je exitp
    mov [handle],eax  ;сохраним дискриптор
    invoke gethostbyname,[InetAddress]  ; попытка отпределяни IP адреса
    cmp eax,0  ; если не удалось
    je exitp  ; то
    mov eax,[eax+0ch]  ; заполение необходимой струкуры
    mov eax,[eax]
    mov cl,[eax]
    mov [InAddr.b1],cl
    mov cl,[eax+1]
    mov [InAddr.b2],cl
    mov cl,[eax+2]
    mov [InAddr.b3],cl
    mov cl,[eax+3]
    mov [InAddr.b4],cl
    
    mov eax,PingBuf
    mov [Reply.Data],eax
    mov [Reply.DataSize],32
    mov al,byte [ttl]
    mov [Optionss.Ttl],al
    mov eax,[InAddr]
    invoke IcmpSendEcho,[handle],eax,PingBuf,32,Optionss,Reply,92,3000  ; пинг
    cmp eax,0
    je exitp
    mov eax,1
    ret
    exitp:
    xor eax,eax
    ret
    endp
    
    proc memo_add texts,hwnd_g  ; процедура добавления и вывода текста на экран (в мемо)
     invoke lstrcat,[memo_buf],[texts] ; добавить текст к буферу
     invoke lstrcat,[memo_buf],crlf ; добавить символ конца строки
     invoke GetDlgItem,[hwnd_g], 105 ; получить адрес мемо
     invoke SendMessage,eax, WM_SETTEXT, 3, [memo_buf] ; вывести буфер
     ret ; возврат из процедуры
    endp ; конец процедуры
    
    proc trace
     push eax ecx
     invoke WSAStartup,$101, WSData ; инит
     stdcall memo_add,'Трассировка начата',[hwndg] ; Вывести данные
     stdcall memo_add,'------------------',[hwndg] ; о начале трасировки
      invoke GetDlgItem,[hwndg], 104  ; адрес edit'a
      invoke GetWindowText,eax,IP_BUF,255  ; считать что там введено
      mov [schet],1  ; счетчик серверов
     traces:
      mov ecx,[schet]
      stdcall Ping,IP_BUF,ecx  ; пропинговать
      cmp eax,0  ; если не пингуется
      je trace_err	; то
      mov eax,[small_buf]  ; очистить временный буфер
      mov [eax],dword 0
      invoke wsprintf,num_buf,formats,[schet]  ; типа inttostr
      add esp,12 ; для очистки стека. т.к. wsprintf почемуто за собой не очищает его
      invoke lstrcat,[small_buf],num_buf  ; добавить к малому буферу номер сервера
      invoke lstrcat,[small_buf],') ['
      invoke inet_ntoa,[Reply.Address] ; определить адрес сервера
      invoke lstrcat,[small_buf],eax  ; добавить к малому буферу IP адрес сервера
      invoke lstrcat,[small_buf],'] '
      invoke gethostbyaddr,Reply.Address, 4, AF_INET  ; определить имя сервера
      cmp eax,0  ; еси имя удалось определить
      jne mmmm ;  то
      invoke lstrcat,[small_buf],'---not host name---'  ; добавить в буфер инфу о том что неудалось определить имя сервера
      jmp mmmm1
      mmmm:
      mov eax,[eax]
      invoke lstrcat,[small_buf],eax  ; добавить к малому буферу имя сервера
      mmmm1:
      stdcall memo_add,[small_buf],[hwndg]	; вывести малый буфер на экран
      inc [schet]  ; увеличить счетчик серверов
      cmp [Reply.Status],0	;если это не последний сервер
      jne traces  ; то
       ; иначе
      stdcall memo_add,'------------------',[hwndg]  ;дабовать в мемо инфу
      stdcall memo_add,'Трассировка закончена',[hwndg]  ; о том что трасировка закончена
      pop ecx eax
    ret  ; возврат из процедуры
    trace_err:   ; Если истекло время
      stdcall memo_add,'Истечение времени ответа',[hwndg]  ; вывести ошибку
      pop ecx eax
    ret ; возврат из процедуры
    endp
    
    
    proc MainProc hwnd,msg,wparam,lparam  ; главная диалоговая процедура
     push ebx esi edi
      ; ---------обработка сообщений-----
     cmp [msg],WM_COMMAND  ; если получина команда
     je main_wmcommand
     cmp [msg],WM_CLOSE  ; если выход
     je main_close
     xor eax,eax  ; еах=0
     jmp main_finish  ; переход на конец процедуры
    
    main_wmcommand:  ; команды
     cmp [wparam],BN_CLICKED shl 16+101
     je main_go
     cmp [wparam],BN_CLICKED shl 16+102
     je main_clear
     jmp main_processed  ; продолжение
    
    main_go:  ; начать трассировку
    mov eax,[hwnd]
    mov [hwndg],eax  ; сохранить дискриптор окна (пригодится)
    invoke CreateThread,0, 0, trace, 0, 0, handle  ; создать поток трассировки (чтобы не вешать прогу)
    jmp main_processed  ; продолжение
    
    main_clear:  ; очистка мемо
     mov eax,[memo_buf]
     mov [eax],dword 0  ; записть первым символом - 0x00
     invoke GetDlgItem,[hwnd], 105
     invoke SendMessage,eax, WM_SETTEXT, 3, [memo_buf]  ; вывести на экран пустой буфер
    
    jmp main_processed  ; продолжение
    
    main_close:  ; выход и программы
     invoke EndDialog,[hwnd],0  ; закрыть диалог
     invoke ExitProcess,0  ; завершить процесс
    
    main_processed:  ; продолжение
     mov eax,1  ; возврат удачности
    
    main_finish:
     pop edi esi ebx
     ret
    endp
    
     ; таблица импорта
    section '.idata' import data readable writeable
    library kernel32,'KERNEL32.DLL',user32,'USER32.DLL',wsock32,'WSOCK32.DLL',icmp,'icmp.dll'
    include 'd:\coding\fasm\include\apia\kernel32.inc'
    include 'd:\coding\fasm\include\apia\user32.inc'
    include 'd:\coding\fasm\include\apia\WSOCK32.inc'
    import icmp,IcmpCreateFile,'IcmpCreateFile',\
    	    IcmpSendEcho,'IcmpSendEcho'
    
     ; секция ресурсов
    section '.rsrc' resource data readable
    directory RT_DIALOG,dialogs
    resource dialogs,100,LANG_RUSSIAN+SUBLANG_DEFAULT,mainform
    
    dialog mainform,'SLESH TraceRoute for Windows',70,70,447,171,DS_MODALFRAME+WS_MINIMIZEBOX+WS_POPUP+WS_CAPTION+WS_SYSMENU
      dialogitem 'BUTTON','TRACE', 101, 353, 2, 45, 14, BS_PUSHBUTTON+BS_FLAT+WS_POPUP+WS_VISIBLE+WS_TABSTOP
      dialogitem 'BUTTON','CLEAR', 102, 400, 2, 45, 14, BS_PUSHBUTTON+BS_FLAT+WS_POPUP+WS_VISIBLE+WS_TABSTOP
      dialogitem 'STATIC','Введите IP / HOST:', 103, 6, 4, 81, 11, SS_CENTER+WS_CHILD+WS_VISIBLE+WS_GROUP
      dialogitem 'EDIT','', 104, 91, 2, 259, 14, ES_LEFT+WS_CHILD+WS_VISIBLE+WS_BORDER+WS_TABSTOP
      dialogitem 'EDIT','', 105, 4, 18, 440, 150, ES_LEFT+ES_MULTILINE+ES_AUTOVSCROLL+ES_AUTOHSCROLL+ES_READONLY+WS_CHILD+WS_VISIBLE+WS_BORDER+WS_VSCROLL+WS_HSCROLL+WS_TABSTOP
    enddialog
    
    
     
    2 people like this.
  2. Necromancer13

    Necromancer13 New Member

    Joined:
    4 Nov 2007
    Messages:
    2
    Likes Received:
    2
    Reputations:
    0
    круто!! АВтору респект! Спасибо!
     
  3. Necromancer13

    Necromancer13 New Member

    Joined:
    4 Nov 2007
    Messages:
    2
    Likes Received:
    2
    Reputations:
    0
    slesh, вопрос конечно не в тему, но все же... мне очень понравилась твоя аватарка:)
    не скажешь, где можно достать еще авики типа этого? а то я блин уже месяц ищу...
     
    2 people like this.