; <--- description ---> ; compiler: FASM 1.67.21 ; name: ICQ for Kolibri ; version: 0.01 ; written by: LV ; e-mail: lv4evil@ya.ru ; <--- include all MeOS stuff ---> include "lang.inc" include "MACROS.INC" purge mov ;include "ASCL9/ascl.inc" ;include "debug.inc" include "editbox.inc" ; <--- start of MenuetOS application ---> MEOS_APP_START ;include "debug.inc" include "2000.inc" include "comp.inc" use_edit_box procinfo,22,5 ; <--- start of code ---> CODE ;mov eax, 40 ;mov ebx, 47h ;int 40h call loaduin call draw_window ; at first create and draw the window ;call buttonbox wait_event: ; main cycle mov eax, 23 mov ebx, 20 int 0x40 cmp eax, 1 ; if event == 1 je redraw ; jump to redraw handler cmp eax, 2 ; else if event == 2 je key ; jump to key handler cmp eax, 3 ; else if event == 3 je button ; jump to button handler ; ; Ждем данных ; mov eax, 53 mov ebx, 2 push ecx mov ecx, [socket] int 0x40 pop ecx cmp eax, 0 jnz read_socket mouse_edit_box inputbox ; ; Если есть соединение с сервером, посылаем пакеты - подтвеждения каждые 60 с ; call sendkeep jmp wait_event ; else return to the start of main cycle redraw: ; redraw event handler call draw_window jmp wait_event key: ; key event handler mov eax, 2 ; get key code int 0x40 cmp ah, 0Dh ; Пробел - отправить сообщение jz send key_edit_box inputbox jmp wait_event button: ; button event handler mov eax, 17 ; get button identifier int 0x40 cmp ah, 2 jz connect cmp ah, 3 jz disconnect cmp ah, 4 jz send ; ; Проверяем, не нажата ли кнопка в КЛ ; 100 2 символов, считается, что передан ; сам уин - для отправки сообщений юзерам, которых нет в КЛ ; mov al, [inputbuff] cmp al, '/' jnz sd_message ; Смена уина ;mov al, [inputbuff+2] ;cmp al, 20h ;jz sd_use_kl mov al, [inputbuff+3] cmp al, 20h ; Пробел jz sd_use_kl ; ; Ищем первый пробел, им должен закончиться уин ; xor ecx, ecx sd_loop: mov al, [inputbuff+ecx] cmp al, 20h jz sd_space cmp al, 0 jz wait_event inc ecx jmp sd_loop sd_space: ; ; Заменяем пробел на 0, отсылаем сообщение mov [inputbuff+ecx], byte 0 lea ebx, [inputbuff+1] lea eax, [inputbuff+ecx+1] call sendmsg mov ebx, 0000FFh call writemsg jmp wait_event sd_use_kl: lea eax, [inputbuff+1] mov [inputbuff+3], byte 0 call ascitoint lea eax, [eax-1] ; Т.к. в КЛ отсчет с 0 mov [curruser], al sd_message: ; ; Сообщение movzx eax, [curruser] mov ebx, UIN_LEN imul ebx, eax lea ebx, [uins+ebx] mov al, [inputbuff] cmp al, '/' jz @f mov eax, inputbuff jmp sd_send @@: ;mov al, [inputbuff+2] ;cmp al, ' ' ;jz @f lea eax, [inputbuff+4] ;jmp sd_send ;@@: lea eax, [inputbuff+3] sd_send: call sendmsg mov ebx, 0000FFh call writemsg jmp wait_event ; ; Есть принятые данные ; read_socket: pushf pushad ;write_debug 'Some data in socket' ; ; Проверяем, не был ли получен заголовок отдельно от данных ; в предыдущем цикле ; cmp [hrf], 1 jz rs_head_recived mov eax, 53 mov ebx, 2 mov ecx, [socket] int 40h cmp eax, 6 ; Flap head size jc r_end ; ; Принимаем заголовок ; xor edx, edx ;mov ecx, [socket] rs_loop: mov eax, 53 mov ebx, 3 int 40h mov [mbuff+edx], bl inc edx cmp edx, 6 jnz rs_loop ; ; Заполняем заголовок ; ;xor eax, eax ; ; Заголовок принят! ; mov [hrf], 1 mov bl, [mbuff] mov [rflap.bId], bl mov bl, [mbuff+1] mov [rflap.bCh], bl mov bh, [mbuff+2] mov bl, [mbuff+3] mov [rflap.wSn], bx mov bh, [mbuff+4] mov bl, [mbuff+5] mov [rflap.wDs], bx ; ; Принимаем данные ; ;xor edx, edx cmp [rflap.bId], 2Ah jnz rs_flap_error ; ; Проверяем, получены ли данные ; rs_head_recived: mov eax, 53 mov ebx, 2 ;mov ecx, [socket] int 40h cmp ax, [rflap.wDs] ; Размер данных jc r_end ; ; mov ax, [rflap.wDs] ; ; Проверяем размер данных ; cmp ax, MBUFF_SIZE+1 jnc rs_big_flap xor esi, esi mov esi, eax xor edx, edx ;mov ecx, [socket] rs_data_loop: cmp edx, esi jz rs_data_end mov eax, 53 mov ebx, 3 int 40h mov [mbuff+edx], bl inc edx jmp rs_data_loop ; ; Данные приняты ; rs_data_end: mov [hrf], 0 write_debug 'Some data recived' ; ; ; cmp [login], 0 jz rs_login call main_loop jmp r_end rs_login: call srv_login ;write_debug 'Exited srv_login' jmp r_end rs_flap_error: write_debug 'Invalid Flap' ; ; FLAP.id неверный. нужно закрыть сокет ; mov ecx, [socket] ;call closesocket jmp r_end ; ; Слишком большой пакет! ; rs_big_flap: write_debug 'Too BIG FLAP Recived' mov [hrf], 0 mov ecx, [socket] mov ax, [rflap.wDs] xor esi, esi mov esi, eax xor edx, edx rs_data_loop2: cmp edx, esi jz r_end mov eax, 53 mov ebx, 3 int 40h ;mov [mbuff+edx], bl inc edx jmp rs_data_loop2 r_end: popad popf jmp wait_event ; Соединение с сервером, возвращает в eax - хэндл сокета ; передаем в еах IP адрес сервера ; в ebx - порт srv_connect: push ecx push edx push esi push edi push ebx mov esi, eax ; IP - в esi ; find free port mov ecx, 1000 ; Определяем локальный порт, начинаем с 1000 getlp: inc ecx push ecx mov eax, 53 mov ebx, 9 int 0x40 pop ecx cmp eax, 0 ; этот локальный порт используется? jz getlp ; да - продолжаем перебирать ;OK ecx = port number ;Open Socket mov eax, 53 mov ebx, 5 xor edx, edx ;mov dx, ICQ_PORT pop edx ;mov esi,ICQ_IP mov edi, 1;SOCKET_ACTIVE int 040h ; mov [socket], eax ; ; Ждем установки соедиения mov ecx, eax srv_loop: mov eax, 53 mov ebx, 6 int 40h cmp eax, TCB_ESTABLISHED jz fin cmp eax, 11 jae @f ; mov eax, 5 mov ebx, 50 int 40h jmp srv_loop ;cmp eax,-1 ;jnz fin ;delay 100 write_debug 'CONNECTION FAILED' ;Подключение не удалось jmp @f ;connrcted: ;CONNECTED fin: write_debug 'Connected!!!!' @@: pop edi pop esi pop edx pop ecx ;pop ebx ret ; ; --> ecx socket handle ; buff db 1024 dup 0 lbuff db 8 dup 0 ; Для 1 пакета от сервера srv_login: pushf push eax push ebx ;push ecx push edx ; ; Определяем тип полученных данных ; movzx eax, [rflap.bCh] cmp eax, 01 jz s_new_connection cmp eax, 04 jz s_cookie ; cookie jmp l_flap_err s_new_connection: ; ; Проверяем полученный пакет ; movzx eax, [rflap.wDs] cmp eax, 4 jnz l_len_err mov eax, dword [mbuff] cmp eax, 01000000h ; 00 00 00 01 jnz l_data_err ; ;Формируем пакет для соединения ; ;mov [flap.bId], FLAP_ID mov [flap.bCh], NEW_CONNECTION mov eax, 26 mov ebx, 9 int 40h mov [seq], ax mov [flap.wSn], ax ; Sequence number ;mov [buff],0 ;mov [buff+1],0 ;mov [buff+2],0 mov dword [buff], 0x01000000 ;login Protokol version 00 00 00 01 ;mov[buff+4],0 mov word [buff+4], 0x0100; TLV.TYPE = UIN 00 01 mov eax, UIN call strlen mov [buff+6], ah mov [buff+7], al ; Length of UIN mov edx, eax add edx, 7 ; в edx длина заполненного буфера mov ecx, eax ;Длина строки mov eax, UIN lea ebx, [buff+8] ; + размер данных в буфере + 1 call strcpy mov eax, PASS call roast mov [buff+edx+2], 2 ; TLV.TYPE - rosted password call strlen mov word [buff+edx+4], ax ; Length of pass add edx, 4 mov ebx, buff add ebx, edx ; назначение add edx, eax ; Сохраняем в EDX длину заполненного буфнра mov ecx, eax ; Длина строки mov eax, PASS ; Источник inc ebx call strcpy mov [buff+edx+2], 3 ; TLV.TYPE - client id string mov eax, ID_STRING call strlen mov word [buff+edx+4], ax add edx, 4 mov ecx, eax mov ebx, buff add ebx, edx add edx, eax inc ebx mov eax, ID_STRING call strcpy mov [buff+edx+2], 016h ; TLV.TYPE - Client id mov [buff+edx+4], 2 mov word [buff+edx+6], ID_NUM add edx, 6 mov [buff+edx+2], 017h ; Client major version mov [buff+edx+4], 2 mov [buff+edx+6], MAJOR add edx, 6 mov [buff+edx+2], 018h ; Client minor version mov [buff+edx+4], 2 mov [buff+edx+6], MINOR add edx, 6 mov [buff+edx+2], 019h ; Client lesser version mov [buff+edx+4], 2 mov [buff+edx+6], LESSER add edx, 6 mov [buff+edx+2], 01Ah ; Client build number mov [buff+edx+4], 2 mov word [buff+edx+6], BUILD add edx, 6 mov [buff+edx+2], 014h ; Client distribution number mov [buff+edx+4], 4 mov [buff+edx+8], DISTR add edx, 8 mov [buff+edx+2], 0Fh ; Client language mov eax, CL_LANG call strlen mov word [buff+edx+4], ax add edx, 4 mov ecx, eax mov ebx, buff add ebx, edx inc ebx add edx, eax mov eax, CL_LANG call strcpy mov [buff+edx+2], 0Fh ; Client language mov eax, CL_COUNTRY call strlen mov word [buff+edx+4], ax add edx, 4 mov ecx, eax mov ebx, buff add ebx, edx inc ebx add edx, eax mov eax, CL_COUNTRY call strcpy ;write_debug 'Connect attemption' ; mov eax, ICQ_IP ; call srv_connect ; cmp eax, -1 ; Подключение не удалось ; jz l_fin ; mov ecx, eax ; mov eax, rflap ; mov ebx, lbuff ; call recvflap ; cmp eax, -1 ; jz l_flap_err ; cmp [rflap.bCh], 01 ; AUTH channel ; jnz l_ch_err ; cmp eax, 4 ; jnz l_len_err ; cmp dword [lbuff+3], dword 1 ; jnz l_data_err mov ecx, [socket] inc dx mov [flap.wDs], dx ; Data size mov eax, flap mov ebx, buff call sendflap cmp eax, 0 jnz l_fin ; Неуспех jmp l_end s_cookie: ;mov eax, rflap ;mov ebx, buff ;call recvflap ;cmp eax, -1 ;jz l_flap_err ;cmp [rflap.bCh], 4 ;jnz l_ch_err ;write_debug 'UIN' xor ebx, ebx uin_loop: xor eax, eax mov ax, word [mbuff+ebx] cmp ax, 0100h ; 00 01 TLV.Type UIN jz l_uin_ok ; Теперь сервер передает еще данные при соединении, а потом опять add ebx, 5 ; тот же TLV 1 cmp ebx, 5 ja l_tlvt_err jmp uin_loop l_uin_ok: mov eax, ebx xor ebx, ebx mov bl, [mbuff+eax+3] ; mov bh, [mbuff+eax+2] ; Длина данных ; ; UIN Пока не проверяется ; lea ebx, [ebx+eax+4] mov ax, word [mbuff+ebx] cmp ax, 0500h ; 00 05 Bos address jz l_all_ok cmp ax, 0400h ; UIN incorrect jz l_uin_err cmp ax, 0800h jz l_pass_err jmp l_tlvt_err ; ; если неверный UIN/ пароль, получаем TLV.TYPE 4/8 ; l_all_ok: xor ecx, ecx mov cl, [mbuff+ebx+3] ;length mov ch, [mbuff+ebx+2] ; lea eax, [mbuff+ebx+4] push ebx mov ebx, bos_address call strcpy pop ebx add ebx, ecx lea ebx, [ebx+4] ; Размер заголовка ; ; cookie ; ;write_debug 'Login Cookie' xor eax, eax mov ax, word [mbuff+ebx] cmp ax, 0600h ; TLV.Type cookie jnz l_tlvt_err mov cl, [mbuff+ebx+3] ; mov ch, [mbuff+ebx+2] ; Length mov [cookie_len], cx lea eax, [mbuff+ebx+4] push ebx mov ebx, srv_cookie call strcpy pop ebx ; ; Соединяемся с BOS ; ;call srv_disconnect mov ecx, [socket] ;write_debug 'Closing socket' ;call closesocket ; ; ;mov eax, 53 ;mov ebx, 8 ;int 40h mov eax, bos_address call ip_parser call htonl data_debug 'BOS Address: ', eax data_debug 'BOS Port: ', ebx mov [bos_ip], eax mov [bos_port], ebx call srv_connect mov [login], 1 ; Соединение с основным сервером установлено ;mov [socket], eax jmp l_end ; ; ; l_pass_err: write_debug 'PASSWORD INVALID' jmp l_fin l_uin_err: write_debug 'UIN INVALID' jmp l_fin l_data_err: write_debug 'LOGIN DATA MISMATCH' jmp l_fin l_len_err: write_debug 'RECIVED DATA LENGTH MISMATCH' jmp l_fin l_tlvt_err: write_debug 'TLV TYPE MISMATCH' jmp l_fin l_ch_err: write_debug 'FLAP CHANNEL MISMATCH' jmp l_fin l_flap_err: write_debug 'FLAP ID MISMATCH / RECIVE ERROR' l_fin: ; ; Необходимо закрыть сокет ; ;call srv_disconnect ;call closesocket l_end: pop edx ;pop ecx pop ebx pop eax popf ret ; ; Length of string ; input eax = offset string ; output eax = strlen ; strlen: push ebx push ecx pushf xor ebx, ebx xor ecx, ecx loop_s: mov cl, [eax+ebx] cmp ecx,0 jz nl inc ebx jmp loop_s nl: mov eax, ebx popf pop ecx pop ebx ret ; ; Roasting password ; EAX = offset password ; roast: pushf push ecx push ebx xor ecx, ecx xor ebx, ebx loop_r: mov bl, [eax+ecx] ;Символ из массива пароля cmp bl, 0 ;Конец строки jz r_fin xor bl, [ROASTING_ARRAY+ecx] mov [eax+ecx], bl inc ecx jmp loop_r r_fin: pop ebx pop ecx popf ret ; ;Copy string of bytes ;В EAX = адрес исходной строки ;В EBX = адрес назначения ;В ECX = длина строки ; strcpy: pushf push esi push edi push ecx cld ;Обрабатываем строку от начала к концу mov esi, eax mov edi, ebx rep movsb pop ecx pop edi pop esi popf ret ; ; Заполняет буфер, по адресу в ebx ; данными, по адресу eax, в ; cx - Тип TLV ; dx - длина данных ; ; tlvstr: ;pushf push edx push ecx push ebx mov [ebx], ch ; Type mov [ebx+1], cl mov [ebx+2], dh ; Length mov [ebx+3], dl lea ebx, [ebx+4] ; EBX = offset of destination mov ecx, edx call strcpy pop ebx pop ecx pop edx ;popf ret ; ; eax - указатель на FLAP_head ; ebx - указатель на массив, заполненный данными ; ecx - хендл сокета ; ; В eax возвращает результат записи в сокет ; sendflap: pushf push edx ;push ecx push esi push ebx push ecx xor edx, edx mov dl, [eax] ; ID byte mov [sbuff], dl mov dl, [eax+1] ; FLAP channel mov [sbuff+1], dl mov dl, [eax+2] ; FLAP datagramm seq number mov [sbuff+3], dl ; меняем местами байты для передачи по сети mov dl, [eax+3] mov [sbuff+2], dl mov dl, [eax+4] ; FLAP data size mov [sbuff+5], dl mov dl, [eax+5] mov [sbuff+4], dl mov dx, word [eax+4] xchg ecx, edx ; ecx - size edx - handle mov eax, ebx ; data mov ebx, sbuff ; dest add ebx, 6 ; + header size call strcpy xchg ecx, edx ; ecx - handle, edx - data size s_wait: mov eax, 53 ; Проверяем состояние сокета. Если соедиение mov ebx, 6 ; установлено - посылаем буфер, если сокет закрыт, уходим int 40h cmp eax, TCB_ESTABLISHED ; установлено jz s_est cmp eax, TCB_CLOSED jz s_fin cmp eax, 12 ; У меня такое было, когда соединение устанавливалось с пустотой :-) jnc s_fin ; mov eax, 5 mov ebx, 1 int 40h ; Ждем jmp s_wait s_est: mov eax, 53 mov ebx, 7 ; писать в сокет ;xchg ecx, edx ; ecx - handle, edx - data length add edx, 6 ; + size of header mov esi, sbuff ; data int 40h s_fin: pop ecx pop ebx pop esi ;pop ecx pop edx popf ret ; ; Принимает пакет из сокета ; eax - указатель на FLAP_head ; ebx - указатель на массив ; ecx - хендл сокета ; Возвращает в eax количество принятых байт в массиве ; ; recvflap: ; pushf ; ; ;push eax ; push ebx ; push esi ; push edi ; push edx ; mov esi, eax ; mov edi, ebx ; ; r_fail: ; mov eax, 53 ; Опрашивааем сокет ; mov ebx, 2 ; в eax количество полученных байт ; int 40h ; ; cmp eax, 6 ; буфер не пустой ; jnc r_ok ; ; mov eax, 53 ; Получаем состояние сокета ; mov ebx, 6 ; ; int 40h ; ; ; cmp eax, TCB_CLOSED ; закрыт - уходим ; jz r_err ; ; ; ;mov eax, 5 ; ждем ; ;mov ebx, 1 ; ;int 40h ; ; уходим ; ; ;jmp r_fail ; jmp rf_fin ; ; r_ok: ; В буфере данные ; ; mov eax, 53 ; mov ebx, 3 ; int 40h ; mov [esi], bl ; flap.bId ; cmp bl, FLAP_ID ; jnz r_err ; ; mov eax, 53 ; mov ebx, 3 ; int 40h ; mov [esi+1], bl ; flap.bCh ; ; mov eax, 53 ; mov ebx, 3 ; int 40h ; mov [esi+3], bl ; flap.wSn старший байт ; ; mov eax, 53 ; mov ebx, 3 ; int 40h ; mov [esi+2], bl ; flap.wSn младший байт ; ; mov eax, 53 ; mov ebx, 3 ; int 40h ; mov [esi+5], bl ; flap.wDs старший байт ; ; mov eax, 53 ; mov ebx, 3 ; int 40h ; mov [esi+4], bl ; flap.wDs младший байт ; ; r_check: ; mov eax, 53 ; Проверяем число полученных байт ; mov eax, 2 ; int 40h ; ; xor ebx, ebx ; mov bx, word [esi+4] ; flap.wDs ; cmp eax, ebx ; jnc r_drr ;>= ; ; mov eax, 68 ; wait ; mov ebx, 1 ; int 40h ; jmp r_check ; ; r_drr: ; ready for data recive ; ; ; xor edx, edx ; mov dx, word [esi+4] ; flap.wDs ; xor esi, esi ; ; rf_loop: ; mov eax, 53 ; mov ebx, 3 ; int 40h ; mov [edi+esi], bl ; inc esi ; cmp esi, edx ; jnz rf_loop ; mov eax, edx ; jmp rf_fin ; ; r_err: ; ;pop ebx ; ;pop eax ; mov eax, -1 ; jmp rf_fin ; ; ; rf_fin: ; pop edx ; pop edi ; pop esi ; pop ebx ; ;pop eax ; popf ; ret ; ; eax - указатель на буфер ; ebx - значение, которым необходимо затолнить. Используется только bl ; ecx - размер ; memset: pushf push edi push eax push ebx push ecx cld mov edi, eax mov eax, ebx rep stosb pop ecx pop ebx pop eax pop edi popf ret ; ; Парсим TLV ; <-- в eax адрес TLV ; <-- в ebx адрес буфера, который нужно заполнить ; --> в ebx длина полученных данных ; --> в eax тип TLV ; tlvpar: pushf ;push esi ;push edi push ecx xor ecx, ecx mov cl, [eax+3] ;TLV.Length mov ch, [eax+2] call strcpy xor eax, eax mov al, [ebx+1] ;TLV.Type mov ah, [ebx] mov ebx, ecx pop ecx ;pop edi ;pop esi popf ret ; ; <-- ECX - хендл сокета, который нужно закрыть ; --> ECX - Результат (Ненадежно) ; closesocket: push eax push ebx mov eax, 53 mov ebx, 8 int 40h mov ecx, eax pop ebx pop eax ret ; ; ecx <-- хендл сокета ; ; srv_disconnect: pushf push eax push ebx mov [flap.bId], FLAP_ID mov [flap.bCh], 4 ;Disconnect xor eax, eax mov ax, [seq] mov [flap.wSn], ax mov [flap.wDs], 0 mov eax, flap mov ebx, buff call sendflap pop ebx pop eax popf ret ; ; <-- eax [bos_address] ; --> eax = IP ADDRESS ; --> ebx = port number ; par_buff db 9 dup 0 ip_parser: pushf push ecx push edx push esi push edi xor ecx, ecx ;xor eax, eax xor ebx, ebx xor edx, edx xor esi, esi xor edi, edi ip_loop: xor eax, eax ;xor edx, edx mov al, [bos_address+ecx] cmp al, '.' jz ip_dot cmp al, 0 jz ip_end_str cmp al, ':' jz ip_colon ;sub al, 30h ;cmp al, 9 ;ja ip_err ; Не цифра mov [par_buff+edx], al inc ecx inc edx jmp ip_loop ip_dot: ;xor eax, eax mov [par_buff+edx], 0 ; Конец строки mov eax, par_buff call ascitoint ;data_debug 'Debug eax: ', eax cmp ecx, 0 ; Не может начинаться с точки jz ip_err shl esi, 8 ; Сдвигаем предыдущий байт add esi, eax inc ecx xor edx, edx ; Счетчик буфера = 0 jmp ip_loop ip_colon: ; : В строке адреса inc edi ; Было : jmp ip_dot ip_end_str: cmp edi, 1 jz @f ; : Не было mov [par_buff+edx], 0 ; Конец строки mov eax, par_buff call ascitoint shl esi, 8 ; Сдвигаем предыдущий байт add esi, eax ;mov eax, esi ; IP в 16 ричной форме ;xor ebx, ebx ; Номера порта нет jmp ip_end @@: ; Было : mov [par_buff+edx], 0 mov eax, par_buff call ascitoint mov ebx, eax jmp ip_end ip_err: xor esi, esi ip_end: mov eax, esi pop edi pop esi pop edx pop ecx popf ret ; ; <-- eax указатель на asci ; --> eax int ; ascitoint: pushf push ebx push ecx push edx push esi push edi xor ebx, ebx xor ecx, ecx xor edx, edx ;xor esi, esi xor edi, edi ati_loop: mov bl, [eax+ecx] cmp bl, 0 ; Конец строки jz ati_str_end cmp bl, 39h ja ati_err ; Не цифра cmp bl, 30h jb ati_err inc ecx jmp ati_loop ati_str_end: ; В ecx длина строки ;dec ecx ; Установим на последний символ add eax, ecx ; Указатель на строку + Длина строки dec eax ati_loop2: cmp edx, ecx jz ati_all push eax sub eax, edx ; Вычесть счетчик movzx ebx, byte [eax] ; В bl символ ;pop eax sub bl, 30h ; Вычисляем 10тичную цифру ;push eax mov eax, ebx ; В eax - цифра mov ebx, 10 ; Множитель xor esi, esi ati_mul: cmp esi, edx ; Умножаем на 10 n раз jz ati_mul_end ;push eax ;mov eax, ebx imul eax, ebx ;mov ebx, eax ;pop eax inc esi jmp ati_mul ati_mul_end: mov ebx, eax ; В ebx вычисленное число pop eax add edi, ebx inc edx jmp ati_loop2 ati_all: mov eax, edi jmp ati_end ati_err: ;ati_str_end: xor eax, eax ati_end: pop edi pop esi pop edx pop ecx pop ebx popf ret ; ; ; <-- ecx хендл сокета ; <-- eax указатель на структуру SNAC_head ; <-- ebx указатель на данные ; <-- edx размер данных ; --> eax результат записи в сокет ; snac_buff db 1024 dup 0 sendsnac: pushf push esi push edi push ebx push edx ;xor ebx, ebx mov esi, ecx ; хендл сокета mov edi, ebx ; Указатель на данные xor ebx, ebx mov bl, [eax] ; mov [snac_buff+1], bl ; Family ID mov bl, [eax+1] ; Конвертируется в BigEndian mov [snac_buff], bl ; mov bl, [eax+2] ; mov [snac_buff+3], bl ; Subtype ID mov bl, [eax+3] ; mov [snac_buff+2], bl ; mov bl, [eax+4] ; mov [snac_buff+5], bl ; mov bl, [eax+5] ; Flags mov [snac_buff+4], bl ; mov bl, [eax+6] ; mov [snac_buff+9], bl ; mov bl, [eax+7] ; mov [snac_buff+8], bl ; mov bl, [eax+8] ; Reqest ID mov [snac_buff+7], bl ; mov bl, [eax+9] ; mov [snac_buff+6], bl ; lea ebx, [snac_buff+10] mov eax, edi ; Указатель на данные ;add ebx, 10 ; + размер заголовка SNAC mov ecx, edx ; размер данных call strcpy mov ecx, esi ; Хендл сокета mov [flap.bId], FLAP_ID mov [flap.bCh], 2 ; Канал для посылки SNAC xor ebx, ebx inc [seq] ; seq Увеличивается на 1 при каждой посылке mov bx, [seq] mov [flap.wSn], bx add edx, 10 ; размер данных + размер заголовка SNAC mov [flap.wDs], dx mov eax, flap mov ebx, snac_buff call sendflap pop edx pop ebx pop edi pop esi popf ret ; Обработка всех пактов, приходящих от сервера ; ECX <-- Хендл сокета ; ; ; ; ; main_loop: pushf ;push eax ;push ebx ;push edx pushad mov ecx, [socket] ; ; ждем пакет ; ;m_loop: ;mov eax, 53 ;mov ebx, 2 ;int 40h ;cmp eax, 6 ; размер заголоака FLAP ;jnc recived ; >= ; ; Уходим ; ;jmp m_fin ;mov eax, 5 ;mov ebx, 5 ;int 40h ;jmp m_loop ; ; есть пакет ; ;recived: ;mov eax, rflap ;mov ebx, rbuff ;call recvflap ; ; Определяем тип принятого FLAP ; xor ebx, ebx mov bl, [rflap.bCh] cmp bl, 1 ; Установка соединения jz m_login cmp bl, 2 jz m_snac ; Получен SNAC cmp bl, 3 jz m_flap_err ; FLAP-level error cmp bl, 4 jz m_close_conn ; Закрытие соединения cmp bl, 5 jz m_keep_alive ; ; ; Обработка рассоединения ; m_close_conn: write_debug 'Another Computer Use YOUR UIN!' call srv_disconnect call closesocket jmp m_fin ; ; обработка соединения ; m_login: ; ; проверяем версию протокола ; xor eax, eax mov al, [mbuff+3] cmp eax, 1 jnz m_login_other ; Не подходит ; ; генерируем случайный seq ; Для этого берем время, прошедшее с момента запуска системы ; mov eax, 26 mov ebx, 9 int 40h mov [seq], ax ; ; Отдаем серверу cookie ; mov [flap.bCh], 1 mov [flap.wSn], ax xor eax, eax mov ax, [cookie_len] add eax, 8 ; TLV len + protocol version len mov [flap.wDs], ax mov dword [buff], 01000000h ; 00 00 00 01 Номер протокола mov word [buff+4], 0600h ; 00 06 TLV.Type mov ax, [cookie_len] mov [buff+6], ah ; mov [buff+7], al ; TLV.Length mov edx, ecx ; edx <-- socket handle mov ecx, eax ; ecx <-- cookie len mov eax, srv_cookie ; Src lea ebx, [buff+8] call strcpy mov ecx, edx ; ecx <-- socket handle mov eax, flap mov ebx, buff call sendflap jmp m_fin m_login_other: jmp m_fin ; ; Как обработать ошибку, я не знаю ; m_flap_err: jmp m_fin ; ; Пока не обрабатывается ; m_keep_alive: jmp m_fin ; ; Получен SNAC ; Распознаем его тип ; m_snac: mov eax, rsnac mov ebx, mbuff call snacpar xor ebx, ebx xor edx, edx mov bx, [rsnac.wFid] mov dx, [rsnac.wSid] cmp bx, 1 jz m_snac_1 ;Generic service controls cmp bx, 2 jz m_snac_2 ;Location services cmp bx, 3 jz m_snac_3 ;Buddy List management service cmp bx, 4 jz m_snac_4 ;ICBM (messages) service cmp bx, 9 jz m_snac_9 ;Privacy management service cmp bx, 015h jz m_snac_15 ;ICQ specific extensions service cmp bx, 013h jz m_snac_13 ;Server Side Information (SSI) service jmp m_other_snac ; ; FAMILY 1 ; m_snac_1: cmp dx, 7 jz m_snac_1_7 cmp dx, 3 jz m_snac_1_3 cmp dx, 018h jz m_snac_1_18 cmp dx, 01Fh jz m_snac_1_f cmp dx, 13h jz m_snac_13 cmp dx, 1 jz m_snac_1_1 jmp m_snac_1_other ; ; Rate limits information response ; m_snac_1_7: ; Отвечаем mov [ssnac.wFid], 1 ; Family mov [ssnac.wSid], 8 ; Subtype mov [ssnac.dRi], 8 mov word [buff], 0100h ; 0001 mov word [buff+2], 0200h ; 0002 mov word [buff+4], 0300h ; 0003 mov word [buff+6], 0400h ; 0004 mov word [buff+8], 0500h ; 0005 mov eax, ssnac mov ebx, buff mov edx, 10 ; Размер данных call sendsnac ; ; Client ask server location service limitations ; mov [ssnac.wFid], 2 ; Family mov [ssnac.wSid], 2 ; Subtype mov [ssnac.dRi], 2 mov eax, ssnac mov ebx, buff xor edx, edx call sendsnac jmp m_fin ; ; Server supported snac families list ; m_snac_1_3: ; ; Server sends supported services list ; ; ; SNAC(01,17) ; Client ask for services version numbers ; mov [ssnac.wFid], 1 ; Family mov [ssnac.wSid], 17h ; Subtype mov [ssnac.dRi], 17h ; ; Список сервисов, которые нам нужны ; ; xx xx word family number #1 ; xx xx word family version ; ... ... ... ; ; ; Поправил из дампа &RQ ; mov word [buff], 0100h ; 0001 mov word [buff+2], 0300h ; 0003 mov word [buff+4], 1300h ; 0013 mov word [buff+6], 0200h ; 0002 mov word [buff+8], 0200h ; 0002 mov word [buff+10], 0100h ; 0001 mov word [buff+12], 0300h ; 0002 mov word [buff+14], 0100h ; 0001 mov word [buff+16], 1500h ; 0015 mov word [buff+18], 0100h ; 0001 mov word [buff+20], 0400h ; 0004 mov word [buff+22], 0100h ; 0001 mov word [buff+24], 0600h ; 0006 mov word [buff+26], 0100h ; 0001 mov word [buff+28], 0900h ; 0009 mov word [buff+30], 0100h ; 0001 mov word [buff+32], 1300h ; 0013 mov word [buff+34], 0400h ; 0004 mov word [buff+36], 1500h ; 0015 mov word [buff+38], 0400h ; 0004 mov word [buff+40], 1000h ; 0010 mov word [buff+42], 0100h ; 0001 mov eax, ssnac mov ebx, buff mov edx, 44 call sendsnac jmp m_fin ; ; Server services versions ; m_snac_1_18: ; ; Обработки пока нет ; ; ; Client ask server for rate limits info ; SNAC(01,06) ; mov [ssnac.wFid], 1 ; Family mov [ssnac.wSid], 6 ; Subtype mov [ssnac.dRi], 6 mov eax, ssnac mov ebx, buff xor edx, edx call sendsnac jmp m_fin ; ; Requested online info response ; m_snac_1_f: ; ;Тут должна быть наша информация, пока обработки нет ; jmp m_fin ; ; Message of the day (MOTD) ; m_snac_1_13: ; ; Нечего обрабатывать :-)) ; jmp m_fin ; ; Сообщение об ошибке ; m_snac_1_1: xor eax, eax mov ax, word [mbuff+10] call ntohs data_debug 'SERVER SEND ERROR #', eax jmp m_fin m_snac_1_other: data_debug 'Unknown SNAC Family 1 recived, type ', edx jmp m_fin ; ; Family 2 ; m_snac_2: cmp dx, 3 jz m_snac_2_3 jmp m_snac_2_other ; ; Server replies via location service limitations ; m_snac_2_3: ; ; Обработки пока нет ; ; ; посылаем capabilities / profile ; mov [ssnac.wFid], 2 ; Family mov [ssnac.wSid], 4 ; Subtype mov [ssnac.dRi], 4 ;mov eax, CAPABILITIES ;mov ebx, buff ;push ecx ;mov ecx, 5 ; TLV.Type(0x05) - CLSID values ;mov edx, C_LEN ;call tlvstr ;pop ecx mov word [buff], 0500h ; 00 05 mov eax, C_LEN call htons mov word [buff+2], ax push ecx mov eax, CAPABILITIES lea ebx, [buff+4] mov ecx, C_LEN call strcpy pop ecx mov eax, ssnac mov ebx, buff mov edx, C_LEN+4 ; Длина данных+размер заголовка TLV call sendsnac ; ; запрашиваем server BLM service limitations ; mov [ssnac.wFid], 3 ; Family mov [ssnac.wSid], 2 ; Subtype mov [ssnac.dRi], 2 mov eax, ssnac mov ebx, buff xor edx, edx call sendsnac jmp m_fin m_snac_2_other: write_debug 'Unknown SNAC Family 2 Recived' jmp m_fin ; ; FAMILY 3 ; m_snac_3: cmp dx, 3 jz m_snac_3_3 cmp dx, 0Bh jz m_snac_3_b cmp dx, 0Ch jz m_snac_3_c jmp m_snac_3_other ; ; Server replies via BLM service limitations ; m_snac_3_3: ; ; Обработки пока нет ; ; ; Client ask server for ICBM service parameters ; mov [ssnac.wFid], 4 ; Family mov [ssnac.wSid], 4 ; Subtype mov [ssnac.dRi], 4 ; request-id mov eax, ssnac mov ebx, buff xor edx, edx call sendsnac jmp m_fin ; ; User online notification ; m_snac_3_b: ; ; Из всей информации пока нужен только статус ; xor edx, edx ; Счетчик xor ecx, ecx xor eax, eax cld ; В направлении увеличения адресов dec edx m_snac_3_b_loop: inc edx cmp edx, UINS jnc m_snac_3_b_end ;>= mov cl, [mbuff+10] ; Длина УИН mov eax, ecx mov edi, UIN_LEN imul edi ,edx lea edi, [uins+edi] lea esi, [mbuff+11] repe cmpsb jnz m_snac_3_b_loop ; ; UIN Определен ; lea ecx, [eax+10+11] ; +sizeof SNAC_head + offset #2 TLV mov ax, word [mbuff+ecx] ;#2 TLV.Type cmp ax, 0C00h ;dc info (optional) jz m_snac_3_b_dc cmp ax, 0A00h ;external ip address jz m_snac_3_b_extip jmp m_snac_3_b_bad_tlv m_snac_3_b_dc: ; ; Пропускаем этот TLV ; lea ecx, [ecx+41] m_snac_3_b_extip: ; ; И этот :-) lea ecx, [ecx+8] mov ax, word [mbuff+ecx] cmp ax, 0600h ;TLV.Type(0x0A) - external ip address jz m_snac_3_b_status jmp m_snac_3_b_bad_tlv m_snac_3_b_status: ; ; наконец-то статус 8-) ; mov eax, dword [mbuff+ecx+4] call ntohl ;mov ebx, 4 ;imul ebx, edx ;mov [stats+ebx], eax mov ecx, eax mov ebx, NAME_LEN imul ebx, edx lea ebx, [names+ebx] mov eax, edx call loadbb jmp m_fin m_snac_3_b_bad_tlv: write_debug 'TLV Type Mismatch in SNAC(3,b)' jmp m_fin m_snac_3_b_end: write_debug 'UIN not in local Contact List' jmp m_fin m_snac_3_c: ; ; User offline notification ; xor edx, edx xor ecx, ecx dec edx m_snac_3_c_loop: inc edx cmp edx, UINS jnc m_snac_3_b_end ;>= mov cl, [mbuff+10] ; Длина УИН mov edi, UIN_LEN imul edi ,edx lea edi, [uins+edi] lea esi, [mbuff+11] repe cmpsb jnz m_snac_3_c_loop ; ; UIN Определен ; ;mov eax, -1 ;mov ebx, 4 ;imul ebx, edx ;mov [stats+ebx], eax mov ecx, -1 mov ebx, NAME_LEN imul ebx, edx lea ebx, [names+ebx] mov eax, edx call loadbb jmp m_fin m_snac_3_other: write_debug 'Unknown SNAC Family 3 Recived' jmp m_fin ; ; FAMILY 4 ; m_snac_4: cmp dx, 5 jz m_snac_4_5 cmp dx, 7 jz m_snac_4_7 jmp m_snac_4_other ; ; Server sends ICBM service parameters to client ; m_snac_4_5: ; ; Обработки пока нет ; ; ; Client change default ICBM parameters command ; mov [ssnac.wFid], 4 ; Family mov [ssnac.wSid], 2 ; Subtype mov [ssnac.dRi], 2 ; request-id mov eax, ICBM_PARAMS mov ebx, buff push ecx mov ecx, ICBMP_LEN call strcpy pop ecx mov eax, ssnac mov ebx, buff mov edx, ICBMP_LEN call sendsnac ; ; Client ask server PRM service limitations ; mov [ssnac.wFid], 9 ; Family mov [ssnac.wSid], 2 ; Subtype mov [ssnac.dRi], 2 ; request-id mov eax, ssnac mov ebx, buff xor edx, edx call sendsnac jmp m_fin ; ; Message for client from server ; m_snac_4_7: ; ; Определяем тип сообщения по полю message channel ; xor eax, eax mov ax, word [mbuff+10+8] ; +10 - размер SNAC ; +8 смещение до message channel cmp ax, 0100h ; 00 01 jz m_snac_ch1 cmp ax, 0200h jz m_snac_ch2 cmp ax, 0400h jz m_snac_ch4 jmp m_ch_other ; ; channel 1 plain text ; m_snac_ch1: ; ; Т.к в очередной раз описание протокола не совпадает с реальностью ; разбираем все TLV по порядку mov eax, dword [mbuff+10] ; cookie mov [msg_cookie1], eax mov eax, dword [mbuff+10+4] mov [msg_cookie2], eax ; Используются для потверждения приема сообщений mov al, [mbuff+10+10] ; Sender UIN length mov [ui.bUinLength], al push ecx movzx ecx, al lea eax, [mbuff+10+11] ; UIN string lea ebx, [ui.bUin] ; Dest call strcpy lea ecx, [ecx+10+15] ; первый TLV m_snac_ch1_loop: movzx eax, word [mbuff+ecx] cmp eax, 0100h ;TLV.Type(0x01) - user class jz m_snac_ch1_1 cmp eax, 0600h ;TLV.Type(0x06) - user status jz m_snac_ch1_6 cmp eax, 0800h ; Unknown type jz m_snac_ch1_8 cmp eax, 0500h ; Unknown type jz m_snac_ch1_5 cmp eax, 0F00h ; TLV.Type(0x0f) - user idle time jz m_snac_ch1_f cmp eax, 0300h ; TLV.Type(0x03) - account creation time jz m_snac_ch1_3 cmp eax, 0400h ; TLV.Type(0x04) - automated response flag jz m_snac_ch1_4 cmp eax, 0200h ; TLV.Type(0x02) - message data jz m_snac_ch1_mess jmp m_snac_msg_tlv_err ; ; Возможно, дополнительная ииформация будет обрабатываться ; но пока нет m_snac_ch1_1: movzx eax, word [mbuff+ecx+2] ; TLV.Length call ntohs lea ecx, [eax+ecx+4] jmp m_snac_ch1_loop m_snac_ch1_6: mov eax, dword [mbuff+ecx+4] ; User status call ntohl mov [ui.dUserStatus], eax movzx eax, word [mbuff+ecx+2] ; TLV.Length call ntohs lea ecx, [eax+ecx+4] ; ; jmp m_snac_ch1_loop m_snac_ch1_8: movzx eax, word [mbuff+ecx+2] ; TLV.Length call ntohs lea ecx, [eax+ecx+4] jmp m_snac_ch1_loop m_snac_ch1_5: movzx eax, word [mbuff+ecx+2] ; TLV.Length call ntohs lea ecx, [eax+ecx+4] jmp m_snac_ch1_loop m_snac_ch1_f: movzx eax, word [mbuff+ecx+2] ; TLV.Length call ntohs lea ecx, [eax+ecx+4] jmp m_snac_ch1_loop m_snac_ch1_3: movzx eax, word [mbuff+ecx+2] ; TLV.Length call ntohs lea ecx, [eax+ecx+4] jmp m_snac_ch1_loop m_snac_ch1_4: ;movzx eax, word [buff+ecx+2] ; TLV.Length lea ecx, [ecx+4] jmp m_snac_ch1_loop m_snac_ch1_mess: ; ; movzx eax, word [mbuff+ecx+4] ; cmp eax, 0105h ; 05 fragment identifier (array of required capabilities) jnz m_snac_ch1_fr_err ; 01 fragment version movzx eax, word [mbuff+ecx+6] ; Length call ntohs lea ecx, [ecx+eax+8] ; Пропускаем byte array of required capabilities (1 - text) movzx eax, word [mbuff+ecx] ; fragment identifier (message text) cmp eax, 0101h ; fragment version jnz m_snac_ch1_fr_err movzx eax, word [mbuff+ecx+2] ; TLV Length call ntohs xchg eax, ecx lea eax, [eax+8] ; Начало текстового сообщения lea ecx, [ecx-4] ; - sizeof Message charset number, Message charset subset push eax push ecx ; ; Выводим Message From UIN ; mov eax, MESS call strlen mov ecx, eax mov eax, MESS mov ebx, buff call strcpy lea ebx, [ebx+ecx] lea eax, [ui.bUin] movzx ecx, byte [ui.bUinLength] call strcpy mov [ebx+ecx], byte 0 mov eax, buff xor ebx, ebx call writemsg ; ; Само сообщение ; pop ecx pop eax lea eax, [mbuff+eax] mov ebx, buff call strcpy mov [ebx+ecx], byte 0 mov eax, buff call win2dos mov ebx, 00FF0000h call writemsg ; ; Подтверждаем прием ; pop ecx ; ; Пока не реализовано, т.к. не могу найти клиент, который это использует :-) ; jmp m_fin m_snac_msg_tlv_err: write_debug 'TLV TYPE MISMATCH' pop ecx jmp m_fin m_snac_ch1_fr_err: write_debug 'UNKNOWN FRAGMENT IDENTIFIER OR FRAGMENT VERSION' ;m_snac_ch1_end: pop ecx jmp m_fin ; ; Channel 2 message format (rtf messages, rendezvous) ; m_snac_ch2: ; ; отправим сообщение, что канал не поддерживается ; нужны куки и уин mov eax, dword [mbuff+10] mov [msg_cookie1], eax mov eax, dword [mbuff+10+4] mov [msg_cookie2], eax mov al, [mbuff+10+10] ; Sender UIN length mov [ui.bUinLength], al push ecx movzx ecx, al lea eax, [mbuff+10+11] ; UIN string lea ebx, [ui.bUin] ; Dest call strcpy mov [ssnac.wFid], 4 ; Family mov [ssnac.wSid], 0Bh ; Subtype mov [ssnac.dRi], 0Bh mov eax, [msg_cookie1] mov dword [buff], eax mov eax, [msg_cookie2] mov dword [buff+4], eax mov word [buff+8], 0200h ; Channel 2 mov al, [ui.bUinLength] mov [buff+10], al lea eax, [ui.bUin] lea ebx, [buff+11] call strcpy lea ecx, [ecx+11] mov word [buff+ecx], 0100h ; reason code (1 - unsupported channel, 2 - busted payload, 3 - channel specific) mov edx, ecx pop ecx mov eax, ssnac mov ebx, buff call sendsnac jmp m_fin ; ; Channel 4 message format (typed old-style messages) ; m_snac_ch4: m_ch_other: write_debug 'Unknown message channel' jmp m_fin m_snac_4_other: write_debug 'Unknown SNAC Family 4 recived' jmp m_fin ; ; FAMILY 9 ; m_snac_9: cmp dx, 3 jz m_snac_9_3 jmp m_snac_9_other ; ; Server sends PRM service limitations to client ; m_snac_9_3: ; ; Обработки пока нет ; ; Отключено, тк не поддерживается SIQ ; ; ; Client ask server for SSI service limitations ; ;mov [ssnac.wFid], 13h ; Family ;mov [ssnac.wSid], 2 ; Subtype ;mov [ssnac.dRi], 2 ; request-id ;mov eax, ssnac ;mov ebx, buff ;xor edx, edx ;call sendsnac ; ; последняя стадия соединения ; ; ; Запрашиваем свою информацию ; mov [ssnac.wFid], 1 ; Family mov [ssnac.wSid], 0Eh ; Subtype mov [ssnac.dRi], 0Eh ; request-id mov eax, ssnac mov ebx, buff xor edx, edx ; TLV head len call sendsnac ; ; Client sends its DC info and status to server ; mov [ssnac.wFid], 1 ; Family mov [ssnac.wSid], 1Eh ; Subtype mov [ssnac.dRi], 1Eh ; request-id mov [buff], 0 ; TLV type 06 mov [buff+1], 6h ; mov [buff+2], 0 ; TLV data length mov [buff+3], 4 ; ; ; mov ax, STATUS_DCDISABLED ; DC disabled call htons mov word [buff+4], ax mov ax, STATUS_ONLINE mov [status], ax mov word [buff+6], ax mov eax, ssnac mov ebx, buff mov edx, 8 ; TLV head len+ data len call sendsnac ; ; Выгружаем на сервер КЛ ; call uploadkl ; ; Выгружаем инвизибл лист, пока пустой ; mov [ssnac.wFid], 9 ; Family mov [ssnac.wSid], 7 ; Subtype mov [ssnac.dRi], 7 mov eax, ssnac mov ebx, buff xor edx, edx call sendsnac ; ; В &RQ Есть пакет установки разрешений. я использую его без изменения ; т.к. не знаю, что он содержит ; mov [ssnac.wFid], 15 ; Family mov [ssnac.wSid], 2 ; Subtype mov [ssnac.dRi], 2 mov word [buff], 0100h ; 00 01 encapsulated META_DATA mov word [buff+2], 1000h ; 00 10 Len mov word [buff+4], 000Eh ; LE Len mov word [buff+10], 07D0h ; META_DATA_REQ mov eax, UIN call ascitoint mov dword [buff+6], eax mov word [buff+12], 0102h ; request sequence number (incrementing) mov word [buff+14], 0424h ; META_SET_PERMS_USERINFO mov [buff+16], 1 ; authorization (1-required, 0-not required) mov [buff+17], byte 0 ; webaware (0-no, 1-yes) mov [buff+18], 1 ; dc_perms (0-any, 1-contact, 2-authorization) mov [buff+19], 0 ;unknown mov eax, ssnac mov ebx, buff mov edx, 20 ; ; Client READY command ; mov [ssnac.wFid], 1 ; Family mov [ssnac.wSid], 2 ; Subtype mov [ssnac.dRi], 2 ; request-id mov eax, FAMILY_ARR mov ebx, buff push ecx mov ecx, FA_LEN call strcpy pop ecx mov eax, ssnac mov ebx, buff mov edx, FA_LEN call sendsnac ; ; Запрашиваем offline сообщения ; mov [ssnac.wFid], 15h ; Family mov [ssnac.wSid], 2 ; Subtype mov [ssnac.dRi], 2 ; request-id mov word [buff], 0100h ; TLV type 01 mov word [buff+2], 0A00h ; 00 0a Длина mov word [buff+4], 0008h ; 08 00 mov eax, UIN call ascitoint mov dword [buff+6], eax mov [buff+10], 003Ch ; 3C 00 - Запрос на оффлайновые сообщения mov [buff+12], 0002 ; 02 00 - request sequence number mov edx, 14 ; Общий размер данных в буфере mov eax, ssnac mov ebx, buff call sendsnac ; ; Запрашиваем информацию всех UIN ; call getinfo ; ; завершено соединение ; mov [login], 2 jmp m_fin m_snac_9_other: write_debug 'Unknown SNAC Family 9 Recived' jmp m_fin ; ; FAMILY 13 ; m_snac_13: cmp dx, 3 jz m_snac_13_3 cmp dx, 0fh jz m_snac_13_F jmp m_snac_13_other ; ; Server sends SSI service limitations to client ; m_snac_13_3: ; ; Обработки пока нет ; ; ; SNAC(13,05) Client check if its local SSI copy is up-to-date ; mov [ssnac.wFid], 13h ; Family mov [ssnac.wSid], 5 ; Subtype mov [ssnac.dRi], 5 ; request-id mov eax, ssnac ; 3D E7 48 17 mov [buff], 03Dh ; mov [buff+1], 0E7h ; modification date/time of client local SSI copy mov [buff+2], 48h ; mov [buff+3], 17h ; ; 00 10 mov [buff+4], 00 ; mov [buff+5], 10h ; number of items in client local SSI copy mov ebx, buff mov edx, 5 call sendsnac jmp m_fin ; ; Server tell client its local copy up-to-date ; m_snac_13_F: ; ; Обработки нет ; ; ; Client activates server SSI data ; mov [ssnac.wFid], 13h ; Family mov [ssnac.wSid], 7 ; Subtype mov [ssnac.dRi], 7 ; request-id mov eax, ssnac mov ebx, buff xor edx, edx call sendsnac ; ; последняя стадия соединения ; ; ; Client sends its DC info and status to server ; mov [ssnac.wFid], 1 ; Family mov [ssnac.wSid], 1Eh ; Subtype mov [ssnac.dRi], 1Eh ; request-id mov [buff], 0 ; TLV type 06 mov [buff+1], 6h ; mov [buff+2], 0 ; TLV data length mov [buff+3], 4 ; ; ; mov ax, STATUS_DCDISABLED ; DC disabled call htons mov word [buff+4], ax mov ax, STATUS_ONLINE mov [status], ax mov word [buff+6], ax mov eax, ssnac mov ebx, buff mov edx, 8 ; TLV head len+ data len call sendsnac ; ; Client READY command ; mov [ssnac.wFid], 1 ; Family mov [ssnac.wSid], 2 ; Subtype mov [ssnac.dRi], 2 ; request-id mov eax, FAMILY_ARR mov ebx, buff push ecx mov ecx, FA_LEN call strcpy pop ecx mov eax, ssnac mov ebx, buff mov edx, FA_LEN call sendsnac ; ; Запрашиваем offline сообщения ; mov [ssnac.wFid], 15h ; Family mov [ssnac.wSid], 2 ; Subtype mov [ssnac.dRi], 2 ; request-id mov word [buff], 0100h ; TLV type 01 mov word [buff+2], 0A00h ; 00 0a Длина mov word [buff+4], 0008h ; 08 00 mov eax, UIN call ascitoint mov dword [buff+6], eax mov [buff+10], 003Ch ; 3C 00 - Запрос на оффлайновые сообщения mov [buff+12], 0002 ; 02 00 - request sequence number mov edx, 14 ; Общий размер данных в буфере mov eax, ssnac mov ebx, buff call sendsnac jmp m_fin m_snac_13_other: write_debug 'Unknown SNAC Family 13 Recived' jmp m_fin ; ; Family 15 ; m_snac_15: cmp dx, 3 jz m_snac_15_3 jmp m_snac_15_other ; ; Server sends message #N ; m_snac_15_3: ; ; Определяем подтип принятого пакета ; ;write_debug 'SNAC 15, 3' xor eax, eax mov ax, word [mbuff+10] ; + SNAC.head size cmp ax, 0100h ; 00 01 TLV type jnz m_snac_tlv_err mov ax, word [mbuff+10+10] cmp ax, 0041h ; Offline Message jz m_snac_offline_mes cmp ax, 0042h ; End messages jz m_snac_offline_end cmp ax, 07DAh jz m_snac_meta_data write_debug 'Unknown Subtype SNAC (15,3)' jmp m_fin m_snac_offline_mes: mov eax, MESS ; call strlen ; Выводим строку с сообщением о отправителе и времени отправки push ecx ; mov ecx, eax ; mov eax, MESS mov ebx, buff call strcpy mov eax, dword [mbuff+14+10] ; Sender UIN lea ebx, [buff+ecx] ; После строчки о сообщении call int2strd lea ebx, [ebx+eax] mov [ebx], byte ' ' inc ebx ; + Длина UIN movzx eax, byte [mbuff+21+10] ; Day call int2strd lea ebx, [ebx+eax] mov [ebx], byte '.' inc ebx movzx eax, byte [mbuff+20+10] ;Mounth call int2strd lea ebx, [ebx+eax] mov [ebx], byte ' ' inc ebx movzx eax, [mbuff+22+10] ; Hour call int2strd lea ebx, [ebx+eax] mov [ebx], byte ':' inc ebx movzx eax, [mbuff+23+10] ; Minute call int2strd lea ebx, [ebx+eax] ;mov [ebx], byte ' ' ;inc ebx mov [ebx], byte 0 ; Str end mov eax, buff xor ebx, ebx call writemsg movzx ecx, word [mbuff+26+10] ; Длина соообщения lea eax, [mbuff+28+10] mov ebx, buff call strcpy mov [ebx+ecx], byte 0 mov eax, buff call win2dos ;перекодируем mov ebx, 00FF0000h ;Цвет call writemsg pop ecx jmp m_fin m_snac_offline_end: ; ; Удаляем сообщения на сервере ; mov [ssnac.wFid], 15h ; Family mov [ssnac.wSid], 2 ; Subtype mov [ssnac.dRi], 0602h ; request-id mov word [buff], 0100h ; 00 01 TLV.Type(1) - encapsulated META_DATA1 mov word [buff+2], 0A00h ; 00 0A TLV.Length mov word [buff+4], 0008h ; 08 00 data chunk size (TLV.Length-2) mov eax, UIN call ascitoint mov dword [buff+6], eax ; xx xx xx xx (LE) client uin mov word [buff+10], 003Eh ; 3E 00 (LE) data type: delete offline msgs request cmd mov word [buff+12], 0007h ; xx xx (LE) request sequence number mov edx, 14 ; Размер данных mov eax, ssnac mov ebx, buff call sendsnac jmp m_fin ; ; Ответ на запрос о пользователях ; m_snac_meta_data: ; ; Определяем очередной подтип :-) ; mov ax, word [mbuff+10+14] cmp ax, 0104h ;data subtype: META_SHORT_USERINFO jz m_snac_short_userinfo cmp ax, 00C8h jz m_snac_basic_userinfo ;data subtype: META_BASIC_USERINFO write_debug 'Unknown META DATA subtype' jmp m_fin m_snac_short_userinfo: ; ; Из всей информации пока нужен только ник ; mov al, [mbuff+10+16] cmp al, 0Ah ;success byte jnz m_fin movzx eax, word [mbuff+10+12] ;request sequence number ; ; В запросе я использовал порядковый номер юзера в КЛ lea ebx, [mbuff+10+19] ;nickname string ; Длина строки не нужна, т.к. строка Null-Terminated ;Определяем статус mov ecx, 4 imul ecx, eax mov ecx, [stats+ecx] call loadbb jmp m_fin ; ; тк SIQ на запрос короткой инфы отвечает ; пакетом базовой информации, реализую пока только его ; m_snac_basic_userinfo: mov al, [mbuff+10+16] cmp al, 0Ah ;success byte jnz m_fin movzx eax, word [mbuff+10+12] ;request sequence number ; ; В запросе я использовал порядковый номер юзера в КЛ lea ebx, [mbuff+10+19] ;nickname string ; Длина строки не нужна, т.к. строка Null-Terminated ;Определяем статус mov ecx, 4 imul ecx, eax mov ecx, [stats+ecx] call loadbb jmp m_fin m_snac_tlv_err: write_debug 'TLV TYPE MISMATCH' jmp m_fin m_snac_15_other: write_debug 'Unknown SNAC Family 15 Recived' jmp m_fin m_other_snac: write_debug 'Unknown SNAC recived' jmp m_fin m_fin: ;pop edx ;pop ebx ;pop eax popad popf ret ; Для перевода DWORD из Little Endian в Big Endian ; и наоборот :-) ; <--EAX DWORD ; -->EAX ; ntohl: htonl: ;pushf push ebx ;push ecx xor ebx, ebx mov bl, ah mov bh, al shl ebx, 16 shr eax, 16 mov bl, ah mov bh, al mov eax, ebx ;pop ecx pop ebx ;popf ret ; Для перевода WORD из Little Endian в Big Endian ; <--AX WORD ; -->AX WORD ; ntohs: htons: ;pushf push ebx xor ebx, ebx mov bl, ah mov bh, al mov eax, ebx pop ebx ;popf ret ; ; парсит SNAC ; <--EAX указатель на SNAC_head ; <--EBX указатель на буффер ; -->EAX указатель начало данных = buffer+sizeof SNAC_head ; ; snacpar: pushf push ecx ;push edx mov cl, [ebx+1] ; Family (service) id number младший байт mov ch, [ebx] ; старший mov word [eax], cx mov cl, [ebx+3] ; Family subtype id number mov ch, [ebx+2] ; mov word [eax+2], cx mov cl, [ebx+5] ; SNAC flags mov ch, [ebx+4] ; mov word [eax+4], cx ; mov cl, [ebx+7] ; mov ch, [ebx+6] ; mov word [eax+8], cx ; SNAC request id mov cl, [ebx+8] ; mov ch, [ebx+7] ; mov word [eax+6], cx ; add ebx, 10 ;Размер заголовка mov eax, ebx ;pop edx pop ecx popf ret ; ; парсит userinfo block ; FIXIT ; ; userinfopar: ; pushf ; ; ; ; ; ; ; popf ; ret ; ; посылка сообщения ; [eax] <-- текстовый буфер \ ; [ebx] <-- UIN / Null-terminated sendmsg: pushf pushad push eax push ebx mov [ssnac.wFid], 4h ; Family mov [ssnac.wSid], 6 ; Subtype mov [ssnac.dRi], 106h ; request-id ; ; Получаем время с запуска системы, для cookie ; mov eax, 26 mov ebx, 9 int 40h mov dword [buff], eax ; Cookie 1 mov dword [buff+4], eax ; Cookie 2 mov word [buff+8], 0100h ; Message channel 00 01 pop ebx mov eax, ebx call strlen mov [buff+10], al mov ecx, eax mov eax, ebx lea ebx, [buff+11] call strcpy lea ecx, [ecx+11] mov word [buff+ecx], 0200h ; TLV.Type(0x02) - message data ;push ecx ; ; TLV.Length mov word [buff+ecx+4], 0105h ; 05 01 01 - fragment version, 05 - fragment identifier mov word [buff+ecx+6], 0100h ; data length mov [buff+ecx+8], 01 ; byte array of required capabilities (1 - text) mov [buff+ecx+9], 01 ; fragment identifier (text message) mov [buff+ecx+10], 01 ; fragment version pop ebx mov eax, ebx call strlen mov edx, eax lea eax, [eax+4] ; Длина сообщения + Message charset number+ Message language number call htons mov word [buff+ecx+11], ax mov eax, edx lea eax, [eax+13] ; + длина служебных данных call htons mov word [buff+ecx+2], ax mov word [buff+ecx+13], 0700h ; Message charset number mov word [buff+ecx+15], 0300h ; Message language number mov eax, ecx mov ecx, edx ; Len lea edx, [eax+17] mov eax, ebx ;Source lea ebx, [buff+edx] ;Dest call strcpy lea ecx, [ecx+edx] ; +String length mov [buff+ecx], byte 0 mov eax, ebx call dos2win mov word [buff+ecx], 0600h ; TLV.Type(0x06) - store message if recipient offline mov word [buff+ecx+2], 0 ; TLV.Length lea edx, [ecx+4] ; +TLV_head length mov eax, ssnac mov ebx, buff mov ecx, [socket] call sendsnac popad popf ret ; ; Запрос информации UINов ; getinfo: pushad pushf ; ; SNAC (15,2) - Meta information request ; mov [ssnac.wFid], 15h ; Family mov [ssnac.wSid], 2 ; Subtype mov [ssnac.dRi], 702h ; request-id mov word [buff], 0100h ;TLV.Type(1) - encapsulated META_DATA mov word [buff+2], 1000h ; 00 10 TLV.Length mov word [buff+4], 000Eh ; (LE) data chunk size (TLV.Length-2) mov eax, UIN call ascitoint mov dword [buff+6], eax ;(LE) request owner uin mov word [buff+10], 07D0h ;data type: META_DATA_REQ ;mov word [buff+12], 0008h ; request sequence number <<<-- Может меняться FIXIT mov word [buff+14], 04BAh ; data subtype: META_SHORTINFO_REQUEST mov ecx, [socket] mov edx, 20 xor esi, esi ; Счетчик xor eax, eax gi_loop: mov ebx, esi mov word [buff+12], bx ; request sequence number mov ebx, UIN_LEN imul ebx, esi mov al, [uins+ebx] cmp al, 0 jz gi_end lea eax, [uins+ebx] call ascitoint mov dword [buff+16], eax mov eax, ssnac mov ebx, buff call sendsnac inc esi cmp esi, UINS jnc gi_end jmp gi_loop gi_end: popf popad ret ; ; Загружаем локальный КЛ на сервер для получения статуса юзеров ; uploadkl: pushf pushad ; ; Add buddy(s) to contact list ; mov [ssnac.wFid], 3 ; Family mov [ssnac.wSid], 4 ; Subtype mov [ssnac.dRi], 4 ; request-id xor esi, esi ; Счетчик xor edx, edx ; Заполнено байт ukk_loop: mov ebx, UIN_LEN imul ebx, esi mov al, [uins+ebx] cmp al, 0 jz ukk_end lea eax, [uins+ebx] call strlen mov [buff+edx], al inc edx mov ecx, eax lea eax, [uins+ebx] ; Source lea ebx, [buff+edx] call strcpy add edx, ecx inc esi cmp esi, UINS jz ukk_end jmp ukk_loop ukk_end: mov eax, ssnac mov ebx, buff mov ecx, [socket] call sendsnac popad popf ret ; ; ; sendkeep: pushf pushad cmp [login], 2 jnz @f mov ax, [timer] cmp ax, 300 ;60 c jb @f mov [timer], 0 mov [flap.bId], FLAP_ID mov [flap.bCh], 5 ;Keep alive mov [flap.wDs], 0 inc [seq] mov ax, [seq] mov [flap.wSn], ax mov eax, flap mov ebx, buff mov ecx, [socket] call sendflap @@: popad popf ret ; <--- initialised data ---> DATA lsz header,\ ru, "KI",\ en, "KI",\ fr, "KI" ; MESS db 'Message from ', 0 CUSER db 'Current user: ', 0 ; ;ICQ_IP = 0x0A00A8C0 ; 192.168.0.10 ICQ_IP = 0x99A10C40 ; flap FLAP_head rflap FLAP_head ; ssnac SNAC_head ; для передачи SNAC rsnac SNAC_head ; для принятого SNAC ; ui UI_head ; User info ; procinfo process_information ; UIN db '123456789',0 PASS db 'coolpass',0 ID_STRING db 'ICQ Inc. - Product of ICQ (TM).2000b.4.65.1.3281.85',0 ;ID_STRING db 'ICQ Inc. - Product of ICQ (TM).2001b.5.17.1.3642.85',0 CAPABILITIES db 053h, 054h, 0, 0, 097h, 0B1h, 027h, 051h, 024h, 03Ch, 043h, 034h, 0ADh, 022h, 0D6h, 0ABh,\ 0F7h, 03Fh, 014h, 092h, 02Eh, 07Ah, 064h, 075h, 0FAh, 0DFh, 04Dh, 0C8h, 088h, 06Fh, 0EAh, 035h,\ 095h, 0FDh, 0B6h, 0DFh, 09h, 046h, 013h, 044h, 04Ch, 07Fh, 011h, 0D1h, 082h, 022h, 044h, 045h,\ 053h, 054h, 0, 0 ; ; From &RQ ; ;CAPABILITIES db 0x09, 0x46, 0x13, 0x49, 0x4C, 0x7F, 0x11, 0xD1, 0x82, 0x22, 0x44, 0x45,\ ;...P.F.IL.TВ"DE ; 0x53, 0x54, 0x00, 0x00, 0x09, 0x46, 0x13, 0x44, 0x4C, 0x7F, 0x11, 0xD1, 0x82, 0x22, 0x44, 0x45,\ ;ST...F.DL.TВ"DE ; 0x53, 0x54, 0x00, 0x00, 0x09, 0x46, 0x13, 0x4E, 0x4C, 0x7F, 0x11, 0xD1, 0x82, 0x22, 0x44, 0x45,\ ;ST...F.NL.TВ"DE ; 0x53, 0x54, 0x00, 0x00, 0x09, 0x46, 0x00, 0x00, 0x4C, 0x7F, 0x11, 0xD1, 0x82, 0x22, 0x44, 0x45,\ ;ST...F..L.TВ"DE ; 0x53, 0x54, 0x00, 0x00, 0x26, 0x52, 0x51, 0x69, 0x6E, 0x73, 0x69, 0x64, 0x65, 0x02, 0x07, 0x09,\ ;ST..&RQinside... ; 0x00, 0x00, 0x00, 0x00 C_LEN = 40h ;C_LEN = 80 ICBM_PARAMS db 0, 0, 0, 0, 0, 0Bh, 01Fh, 040h, 3, 0E7h, 3, 0E7h, 0, 0, 0, 0 ICBMP_LEN = 16 ; ^^^ from &RQ ; ; from &rq ; FAMILY_ARR db 0x00, 0x01, 0x00, 0x03, 0x01, 0x10, 0x04, 0x7B, 0x00, 0x13, 0x00, 0x02, 0x01, 0x10, 0x04, 0x7B,\ 0x00, 0x02, 0x00, 0x01, 0x01, 0x01, 0x04, 0x7B, 0x00, 0x03, 0x00, 0x01, 0x01, 0x10, 0x04, 0x7B,\ 0x00, 0x15, 0x00, 0x01, 0x01, 0x10, 0x04, 0x7B, 0x00, 0x04, 0x00, 0x01, 0x01, 0x10, 0x04, 0x7B,\ 0x00, 0x06, 0x00, 0x01, 0x01, 0x10, 0x04, 0x7B, 0x00, 0x09, 0x00, 0x01, 0x01, 0x10, 0x04, 0x7B,\ 0x00, 0x0A, 0x00, 0x01, 0x01, 0x10, 0x04, 0x7B, 0x00, 0x10, 0x00, 0x01, 0x00, 0x10, 0x06, 0x6A FA_LEN = 50h ; ID_NUM = 010Ah MAJOR = 05h ;MAJOR = 04h ;MINOR = 041h MINOR = 011h LESSER = 01h ;BUILD = 0CD1h BUILD = 0E3Ah DISTR = 055h TCB_ESTABLISHED = 4 TCB_CLOSED = 11 ; CL_LANG db 'en',0 CL_COUNTRY db 'us',0 sbuff db 1024 dup 0 ; Буфер для передачи используется внутри sendflap rbuff db 1024 dup 0 ; Приемный буфер tbuff db 512 dup 0 ; Для TLV srv_cookie db 512 dup 0 ; Куки для авторизации bos_address db 128 dup 0 ; Адрес BOS сервера cookie_len dw 0 ; Длина куки seq dw 0 ; Sequence number bos_ip dd 0 bos_port dd 0 status dw 0 ; status mbuff db 2048 dup 0 ; Для приема MBUFF_SIZE = 2048 hrf db 0 ; Флаг приема заголовка mouse_flag dd 0 socket dd 0 login db 0 msg_cookie1 dd 0 ; Используются для потверждения приема сообщений msg_cookie2 dd 0 ; curruser db 0 ; текущий пользователь, которому будут отправляться сообщения ; - Номер в КЛ по порядку timer dw 0 ;ltest db "ADMIN",0 ; ; EDITBOXES ; inputbuff: rb 512 inputbox edit_box 490,10,460,0xffffff,0x6a9480,0,0xAABBCC,0,511,inputbuff,ed_focus,0,0 ; <--- uninitialised data ---> UDATA MEOS_APP_END ; <--- end of MenuetOS application --->