• Курсы Академии Кодебай, стартующие в мае - июне, от команды The Codeby

    1. Цифровая криминалистика и реагирование на инциденты
    2. ОС Linux (DFIR) Старт: 16 мая
    3. Анализ фишинговых атак Старт: 16 мая Устройства для тестирования на проникновение Старт: 16 мая

    Скидки до 10%

    Полный список ближайших курсов ...

Статья ASM для х86. (5.1.) WinSock – работа с портами

logo_2.png
После вводной части перейдём к практике..
Cетевое хозяйство лежит на балансе виндовых библиотек в числе которых и wsock32.dll. Эта устаревшая либа пришла в наш век из прошлого и опирается на сокеты Беркли юникса – версия её WinSock v1.1. Начиная с Win-2000 мелкософт отошла от старых принципов, и полностью обновила библиотеку до версии 2.0, поместив новоиспечённые функции внутрь отдельной либы ws2_32.dll. Прежняя версия тоже осталась для совместимости с уже написанными на ней программами, только все дорожки из неё ведут опять к усовершенствованной ws2_32.dll. Проверить это можно в Hiew'e, запросив у него экспорт последовательностью Enter->F8->F9:

w32_ws32.png


Таким образом, мы можем с чистой совестью вызывать старые функции, тем-более что некоторые из них wsock32 исполняет всё-таки сама – это getsockopt(), recv(), recvfrom() и т.д. на скрине выше. Однако в новой либе есть и функции, которых нет в предыдущей версии. В этом случае придётся звать их напрямую из ws2_32.dll - они начинаются с приставки WSA_xxx().

Под большим системным замком, в подвале сетевой архитектуры трудятся ещё и драйвера, во-главе которых стоит дров интерфейса с сетевым адаптером NDIS.SYS, и драйвер транспортного протокола TDI. Грязными красками иерархию программной части сети можно расписать так:

tcp_ip_01.png


На рисунке выше видно, что сетевые сокеты не вмешиваются в работу уровня приложений. В их задачи входит принять пакет-данных от софта и обернув его в красивый фантик, отправить получателю на другом конце связи. Сокеты – анархисты. Они не зависят ни от какого протокола, а наоборот подминают их под себя. При создании сокета, в его параметрах мы просто указываем уровень, на котором примем пакет отправителя. Например если в аргументе указать PROTO_IP, то пакет попадёт в наши руки уже после уровня TCP (или UDP). За это время протокол TCP уже мог что-нибудь сотворить с пакетом, и к нам он попадёт уже не "в чём мать родила".

С другой стороны, мы можем создать IP-сокет, который будет отправлять пакетики в сеть сразу с уровня IP. В этом случае TCP уже останется за бортом, и даже не будет знать о наших действиях. Другими словами, непосредственно из прикладной программы у нас имеется легальный доступ к любому уровню стека протоколов TCP/IP. Это открывает большие возможности. Что-то подобное делает например PING, доставая клиентов своими ICMP эхо-запросами.

Если-же мы хотим шифровать исходящий трафик, то делать это лучше на самом-верхнем уровне приложений, ..желательно вообще до стека протоколов, перехватывая непосредственно клавиатурный ввод юзера. А так.. ксорить траф можно на любом из уровней. Только если на другом конце связи его во-время не расшифровать, то из-за несовпадения контрольной суммы протоколы следующих уровней начнут просто дропать такие пакеты, отправляя их к праотцам. То-есть мы должны писать сразу клиент-серверное приложение и придумать для него свой протокол, которой будет расшифровывать наши данные. Это не так сложно, как может показаться на первый взгляд.

sockHome.png


Socket как сущность – это комбинация трёх составляющих: IP-адрес, порт, и протокол. При создании сокета мы должны указать именно эти три аргумента, чтобы он мог присутствовать в системе, как самостоятельная личность:
SOCKET = 127.0.0.1 :69 :UDP.

"Интернет сессия" – это один цикл связи клиента и сервером. Сессия может продолжаться бесконечно, пока одному из участников это не надоест. TCP-cессия состоит из трёх фаз: Привет -> Обмен данными -> Пока! Нужно помнить, что сокеты привязываются к сессиям, и если во-время сессии связь нечаянно оборвётся, то сокет этой сессии становится недействительным, и закрыв его – нужно создать новый. Это основная ошибка, которую допускают новички.

В штанинах XP и 7 для нас припрятаны 32768 резервных сокетов. Такое кол-во позволяет создавать их пачками, для каждой сессии отдельно. Причём половина сокетов может прослушивать входящий трафик (т.н. демоны), а половина работать на приём/передачу. На серверных системах резерва ещё больше, т.к. они обслуживают по-более клиентов за раз, и для каждого нужен свой сокет. При создании большого числа сокетов главное не потеряться в них.

В природе имеются блокирующие и неблокирующие сокеты. Первые работают в синхронном режиме, а вторые в асинхронном. Разница их в том, что блокирующий сокет останавливает ход программы до тех пор, пока не выполнит свою задачу. Этим отличаются устаревшие функции из библиотеки wsock32.dll. Соответственно, неблокирующий НЕ ждёт ответа от сервера, а отправив запрос сразу передаёт управление на сл. участок кода программы. В этом случае, следить за состоянием неблокирующего сокета должна отдельная Call-Back функция. Управлять режимом работы сокета позволяет функция ioctlsocket(), с кодом операции FIONBIO No Blocket I/O.
зы, прелюдия что-то растянусь..


5.1. Под копотом..

Если мы планируем работать с сокетами, то промышленная реализация алгоритма одной сессии выглядит так:
  1. WSAStartup() – инициализация библиотеки wsock32.dll;
  2. soсket() – создание сокета определённого типа;
  3. bind() – привязать к этому сокету сетевой адрес собеседника (IP, порт, протокол);
  4. connect() – попытка соединения с ним..;
  5. send() – если связь установлена, то отправить собеседнику пакет данных;
  6. recv() – принять от него ответный пакет;
  7. --- здесь если надо, то крутим цикл send() ---
  8. shutdown() – попрощаться с абонентом, и разорвать соединение;
  9. closesocket() – освободить занимаемый сокет.
Мда.. не радужная перспектива..
На самом деле не всё так плохо, ведь перед нами самый сложный протокол из всех – протокол надёжной связи TCP. Если сокет у нас TCP, то мы можем убрать bing(), поскольку функция connect() сама привязывает сетевой адрес к сокету. А вот в случае с UDP ничто не мешает отправить на скамейку запасных функции connect() и shutdown(), т.к. это протокол без предварительной установки связи. Однако пролог алгоритма в виде первых трёх функций должен присутствовать всегда.

Ещё одна тонкость связана с форматом сетевых адресов, таких как IP и номер порта – функциям WinSock их нужно передавать в прямом порядке Big-Endian, в то время-как процессоры Intel/AMD используют обратный порядок байт Litle-Endian. Например IP-адрес 127.0.0.1 будет находится в памяти процессора как 4-байтное значение: 01 00 00 7F – это и есть LitleEndian, когда младший байт первый. Но функции WinSock требуют прямого порядка как мы записываем их на бумажке, т.е. 7F 00 00 01 или Big-Endian. Под этот-же каток попадают и номера портов, только они не 4-байтные, а 2. На сишном жаргоне размер определяется как LONG(4) и SHORT(2).

Для преобразования порядка байт из обычного в сетевой, предусмотрены WinSock функции htonl() и htons(). В дословном переводе это означает "Hex-To-Net-Long" (для преобразования 4 байтных IP-адресов) и "Hex-To-Net-Short" (для 2 байтных номеров порта). Когда сервер нам будет отвечать, ясный-перец он тоже отправит нам IP-адрес и порт в сетевом порядке байт. Если мы захотим их вывести на экран, то должны применить обратное преобразование, для чего имеются функции ntohl() и ntohs() – соответственно для LONG и SHORT. Такая вот хрень с этими адресами..

Ну и альфа-самцом во всей этой кухне является конечно-же файл с инклудами, которыми FASM к сожалению не может похвастаться. В его папке include\api есть wsock32.inc, в котором перечислены все знакомые ему сетевые функции. Ещё в одном дире include\equates под таким-же названием лежит инклуд с описанием служебных WinSock-структур. Здесь конечно разраб фасма Томаш Грыштар чуток подкачал, и перечислил только критические структуры без которых ну совсем уж никак. Поэтому я дополнил этот инклуд своими структурами, которые собирал со-всех источников. Он лежит в скрепке этого топика, а вам нужно просто заменить им текущий, из папки ..\equates. В нём я описал форматы заголовков всех уровней стека, от TCP и до Ethernet фрейма. Внимание!!! Без этого инклуда, представленные ниже программы работать не будут!

Чтобы было без соли, код будем писать консольный, а для ввода-вывода на экран подключим msvcrt.dll с её функциями printf() и scanf(). Первой можно передавать не ограниченное число аргументов, что позволит выводить сразу кучу информации. Вторая scanf() – для ввода с клавиатуры и считается уязвимой (юзер может переполнить приёмный буфер), поэтому выделим для неё резиновый буфф в конце секции-данных и пусть переполняет эту 4К-байтную секцию, пока не надоест. Её можно было-бы заменить на ReadConsole(), которая ограничивает ввод. Но эта read слишком громоздкая для обычного ввода, а мы стремимся к минимализму.


5.1.0. Программа перечисления портов

Начнём с того, что перечислим все зарезервированные порты на своей машине.
Нужно сказать, что среди WinSock-функций есть информационные функции, для которых не нужно создавать сокеты. Они работаю в офф-лайн и тупо предоставляют нам различную инфу. Две из таких функций я оформил в программу ниже – это WSAStartup() и getservbyport(). Первая загружает библиотеку WinSock и возвращает в структуру "WSADATA" её паспорт. Запрашивая смещения из этой структуры, мы можем выводит из неё инфу на экран. Если функция выполняется удачно, то возвращает нуль:

C-подобный:
invoke  WSAStartup, 0x0101, wsa     ;// 0x0101 = запрашиваемая версия v1.1
                                    ;// wsa = указатель на структуру WSADATA
;//-------------------------------------------------------------------------
struct WSADATA                      ;// всего 400 байт (0x190)
   wVersion       dw  0               ; мин.версия WinSock (обычно v1.1)
   wHighVersion   dw  0               ; макс.версия (обычно v2.2)
   szDescription  db  256+1 dup(0)    ; строка с текущей версией
   szSystemStatus db  128+1 dup(0)    ; строка с текущим статусом (Run/Stop)
   iMaxSockets    dw  0               ; сколько TCP-сокетов можно создать
   iMaxUdpDg      dw  0               ; макс.размер UDP-датаграммы
   _padding_      db  2 dup(0)        ; резерв (байты выравнивания)
   lpVendorInfo   dd  0               ; указатель на данные производителя
ends

Вторая функция getservbyport() занимается тем, что по номеру порта заполняет уже свою структуру "servent". Если вызов успешный, то возвращает в EAX указатель на эту структуру, иначе нуль. Смысловая нагрузка приёмного буфера "servent" выглядит так:

C-подобный:
invoke  getservbyport, port, 0      ;// port = номер порта, о котором хотим собрать инфу
                                    ;// 0 = все протоколы (можно фильтровать TCP или UDP)
;//-------------------------------------------------------------------------------------
struct servent          ;// getservbyport (port, *proto)
   s_name       dd  0      ; линк на строку с именем сервиса
   s_aliases    dd  0      ; линк на NULL-массив альтернативных имён
   s_port       dw  0      ; номер порта
   s_zero       dw  0      ; резерв
   s_proto      dd  0      ; линк на строку с именем протокола
ends

Как говорилось выше, WinSock-функции насилуют драйвера TDI и NDIS. Понаблюдать за этим процессом в замочную скважину можно так.. Запускаем системный "Дисчетчер задач" и в меню вид устанавливаем галку "Вывод времени ядра". Теперь в окне "Быстродействие" диспетчера появится вторая шкала красного цвета, которая и покажет время обращения нашей софтины к ядерному уровню драйверов. Как выяснилось, не все функции прибегают к услугам драйвера – некоторые вполне самостоятельны.

Программа ниже выполняет перечисленные действия, и выводит инфу по каждому порту на экран. Вся нагрузка лежит тут на функции getservbyport(), которой в цикле подставляю следующий порт, пока счётчик не достигнет максимального порта под номером 65535. Ещё одна с прозрачным именем gethostname() возвращает имя нашего узла и сбрасывает его в буфер, на который указывает аргумент. Если выполнилась удачно – в EAX возвращает нуль:

C-подобный:
format   pe console
entry    start
include 'win32ax.inc'
;----------
.data
wsa        WSADATA
sPort      servent
wsaInfo    db  13,10,' %s         %s'
           db  13,10,' Sockets count.....: %d'
           db  13,10,' UDP-datagramm size: %d',0
hName      db  13,10,' Host name.........: %s',0
capt       db  13,10
           db  13,10,' Enum Host Port-name v0.1'
           db  13,10,' ============================',0
mes0       db  13,10,' Port  %05d  %s - %s',0
mesEnd     db  13,10,' ============================'
           db  13,10,' Total: %d ports',13,10,0
buff       db  64 dup(0)
count      dd  0
frmt       db  '%s',0
;----------
.code
start:
;// инициализация библиотеки WinSock, и вывод инфы о ней
         invoke  WSAStartup,0x0101,wsa       ;
         push    0 0                         ; обнулить регистры
         pop     ecx edx                     ; ^^^
         mov     eax,wsa.szDescription       ; версия WinSock
         mov     ebx,wsa.szSystemStatus      ; текущий статус
         mov     cx,[wsa.iMaxSockets]        ; всего сокетов в резерве
         mov     dx,[wsa.iMaxUdpDg]          ; макс.размер UDP-датаграммы
        cinvoke  printf,wsaInfo,eax,ebx,ecx,edx   ; выводим шапку

;// Получить имя своего узла
         invoke  gethostname,buff,64
        cinvoke  printf,hName,buff

;// Начало сканирования зарегистрированных портов
        cinvoke  printf,frmt,capt         ; выводим шапку
         mov     ecx,0xffff               ; всего портов 65535 (word)
         xor     eax,eax                  ; начинать с нулевого
@scan:   push    eax ecx                  ; запомнить номер порта и счётчик!
         invoke  htons,eax                ; переводим #порта в сетевой порядок (..s это Short)
         invoke  getservbyport,eax,0      ; заполняем структуру "servent" по номеру порта
         or      eax,eax                  ; если EAX=0 значит ошибка
         jz      @fuck                    ; пропустить..
         inc     [count]                  ; иначе: "servent" заполнена, и счётчик найденых +1
         xor     ebx,ebx                  ; очистить EBX (в EAX сейчас лежит указатель на "servent")
         mov     bx,word[eax+8]           ; BX = номер порта из структуры "servent"
         xchg    bh,bl                    ; поменять байты местами (из Net в Hex порядок)
         mov     edx,[eax+12]             ; EDX = указатель на имя протокола
         mov     ecx,[eax]                ; ECX = указатель на имя связанного с портом сервиса
        cinvoke  printf,mes0,ebx,edx,ecx  ; выводим инфу порта на экран
@fuck:   pop     ecx eax                  ; порт и счётчик на родину!
         inc     eax                      ; следующий номер порта..
         dec     ecx                      ; счётчик -1
         jnz     @scan                    ; повторить, если счётчик не нуль

;// Выводим кол-во найденных портов
        cinvoke  printf,mesEnd,[count]    ;
        cinvoke  scanf,frmt,frmt+5        ; ждём нажатия клавиши..
         invoke  ExitProcess,0            ; на выход!

;//--- Cекция импорта программы  ------
section '.idata' import data readable   ;
library  kernel32,'kernel32.dll',\      ; импортируемые библиотеки
         wsock32,'wsock32.dll',\        ;
         msvcrt,'msvcrt.dll'            ;
import   msvcrt,printf,'printf',scanf,'scanf'  ; эту FASM не знает, опишем вручную

include 'api\kernel32.inc'         ; остальные функции есть в инклудах фасма.
include 'api\wsock32.inc'          ;

byPort.png


На своей тестовой XP я получил всего 86 занятых портов, хотя на семёрке их уже 174.
Здесь видно, что например порт(43) работает по-протоколу TCP и его прослушивает сервис "NicName - Network Information Center", а это Со всеми этими сервисами нужно будет работать по их собственному протоколу! Получается такая каша, разгребсти которую мы сможем только ко-второму пришествию. Для каждого из них имеется своя , в которой описывается способ общения.


5.1.1. Сканер открытых портов

Допустим мы получили список портов. Теперь можно просканировать их и посмотреть, к какому именно порту мы имеем удалённый доступ. Злейшим врагом сканера является файервол (брэндмауэр), который перекрывает кислород всем портам кроме тех, которые админ внёс в список исключений. Таким образом, из 86 портов моей портянки могут быть открыты только некоторые, и наша цель узнать – какие именно.

Суть в том, что мы выбираем узел и пробуем подключиться к каждому из его портов. Если к порту нет доступа, то встречаем ошибку. Поскольку нам нужно устанавливать связь, значит протокол UDP для этих целей не подходит и нужен TCP. Для передачи адреса-узла сокетам и функциям, в WinSock имеется специальная структура "sockaddr_in". Для секетов Беркли это была (теперь устаревшая) структура " in_addr", но её уже отправили на покой и с версии 2.0 заменили новой:

C-подобный:
struct sockaddr_in             ;// всего 16 байт
   sin_family    dw  0            ; тип протокола (всегда AF_INET)
   sin_port      dw  0            ; номер порта
   sin_addr      dd  0            ; 4 байтный IP-адрес узла
   sin_zero      db  8 dup(0)     ; резерв (выравнивание)
ends

Здесь мы видим важное для нас поле sin_port – его и будем менять в цикле, чтобы просканировать все порты данного IP-адреса. Выше говорилось, что с каждому сокету можно привязать только один адрес, но т.к. нам нужно менять в адресном пакете номер порта, значит это будет уже другой адрес. Придётся на каждом шаге закрывать старый сокет, и создавать новый. Если этого не сделать, то функция connect() начнёт атаковать наоборот нас, своими вечными ошибками. Запишем этот факт в свой кэш.. Вот прототип этой функции:

C-подобный:
;// Функция установки связи с удалённым узлом
;//-------------------------------------------
invoke  connect, [s], addr, addr_len

       s – дескриптор сокета;
    addr – указатель на структуру "sockaddr_in";
addr_len – размер этой структуры.

Теперь перенесём всё сказанное в окно FASM'a и получим демонстрационный сканер портов. Скорость его перебора оставляет желать лучшего, и я специально добавил функцию вывода на экран не только открытых портов, но и закрытых, чтобы наглядно видеть шаг (получилось ~1 сек/порт). Чтобы ускорить этот процесс, нужно создать неблокирующий сокет, т.к. в этом примере он блокирующий. Поэтому connect() ждёт результата, что и тормозит повозку.

C-подобный:
format   pe console
entry    start
include 'win32ax.inc'
;//----------
.data
addr     sockaddr_in
wsa      WSADATA
capt     db  13,10
         db  13,10," Port-Scan v0.1"
         db  13,10,' ====================='
         db  13,10,' Please wait...',0
open     db  13,10,' Port  %05d  ***** open',0
close    db  13,10,' Port  %05d  close',0
mes1     db  13,10,' ========================'
         db  13,10,' Scan OK!',0

port     dd  0                       ; текущий порт
s        dd  0                       ; под дескриптор сокета
host     db '127.0.0.1',0            ; кого сканируем
frmt     db  '%s',0                  ; для scanf(), и дальше буфер ввода (там болото нулей)
;//----------
.code
start:  cinvoke  printf,frmt,capt         ; выводим шапку
         invoke  WSAStartup,0x0101,wsa    ; инициализация WinSock

;// Заполняем адресный пакет "sockaddr_in"
         invoke  inet_addr, host            ; IP из строки в Hex
         mov     [addr.sin_addr],eax        ; записать его в поле адреса
         mov     [addr.sin_family],AF_INET  ; протокол = Интернет

;// Начинаем сканирование портов..
@scan:   invoke  htons,[port]               ; #порта в сетевой порядок байт
         mov     [addr.sin_port],ax         ; в пакет адреса его..

         invoke  socket, AF_INET, SOCK_STREAM,0          ; создать TCP сокет (Stream/поток)
         mov     [s],eax                                 ; запомнить его дексриптор
         invoke  connect,[s], addr, sizeof.sockaddr_in   ; пробуем подключиться по адресу
         cmp     eax,-1                                  ; ошибка?
         jnz     @ok                        ; если нет..
        cinvoke  printf,close,[port]        ; иначе: мессага Close и #порта
         jmp     @next                      ;

@ok:    cinvoke  printf,open,[port]         ; порт открыт!
@next:   invoke  closesocket,[s]            ; отработанный сокет на свалку
         inc     [port]                     ; следующий порт..
         cmp     [port],0xffff              ; все порты просканировали?
         jnz     @scan                      ; нет - повторить

;// После (примерно) двух часов - прощальный диалог с юзером
        cinvoke  printf,frmt,mes1         ;
        cinvoke  scanf,frmt,frmt+5        ; ждём нажатия клавиши..
         invoke  ExitProcess,0            ; на выход!

;//---- Секция импорта программы  -----
section '.idata' import data readable
library  kernel32,'kernel32.dll',\
         wsock32,'wsock32.dll',\
         msvcrt,'msvcrt.dll'
import   msvcrt,printf,'printf',scanf,'scanf'

include 'api\kernel32.inc'
include 'api\wsock32.inc'

Любой сканер – это не есть гуд, и чтобы не насканировать себе билеты в Магадан, лучше вообще не заниматься этим (мало-ли хороших дел на свете?). Этот пример тут только для того, чтобы знать откуда исходит угроза, и закрыть все порты на своём узле. Я установил у себя (145 Кб для тестов то-что доктор прописал), и вот его реакция на эту прожку..

Здесь видно, что установка с ним связи на порт(80) прошла успешно, но пока он собирался отправить мне ответ, я уже сбросил соединение, прихлопнув свой сокет внутри цикла как таракана. Остальные порты у меня под фаером, а вы можете проверить свои:

portScan.png


В следующий раз рассмотрим несколько протоколов, попробуем создать свои, пошифруем трафик и много ещё. Было-бы желание и время. Обитать на этом уровень очень интересно, и вдохновляет огромный запас возможностей. Ограничивает их - только наша фантазия.
 
Последнее редактирование:

Marylin

Mod.Assembler
Red Team
05.06.2019
305
1 375
BIT
315
Спасибо, ..только круто это для тех, кто впервые попал в программную часть сети. Это лишь мои попытки донести до начинающих общие принципы сетевой архитектуры, поэтому стараюсь объяснять на пальцах. Те-кто уже в курсе дел, такой материал и читать не будут, т.к. это основы. Однако за бортом остаётся огромная армия неосведомлённых новичков, под которых и заточено сие повествование. Я рад, что это хоть кто-то читает ..значит не зря прожигаю жизнь.
 

Hardreversengineer

Green Team
20.08.2019
49
28
BIT
14
Спасибо, ..только круто это для тех, кто впервые попал в программную часть сети. Это лишь мои попытки донести до начинающих общие принципы сетевой архитектуры, поэтому стараюсь объяснять на пальцах. Те-кто уже в курсе дел, такой материал и читать не будут, т.к. это основы. Однако за бортом остаётся огромная армия неосведомлённых новичков, под которых и заточено сие повествование. Я рад, что это хоть кто-то читает ..значит не зря прожигаю жизнь.
Всегда стоит вернуться к началу, чтобы проверить - не упустил ли ты какую нибудь мелочь. А вообще, всегда думаешь что жизнь проживёшь максимально эффективно, а в итоге 90% всей жизни прожигание её непойми на что, не стоит из-за этого переживать. Мне интересно, вот попробовать не используя какие либо библиотеки, а всё самому, ни на что не опираясь написать.
Кстати, в одной из ваших статей про скрытие процесса было, пользуясь случаем, хочу узнать, а зачем нам нужно парсить включение диспетчера задач, если можно сразу заинжектить ? Или это потому, что сразу это сделать невозможно ? И ещё, а вот будет какая нибудь статья про написание демосцен (ну работа с графикой и тд) ?
 

Marylin

Mod.Assembler
Red Team
05.06.2019
305
1 375
BIT
315
а зачем нам нужно парсить включение диспетчера задач, если можно сразу заинжектить ?
Обычно инжектят в память, а для этого процесс диспетчера должен быть запушен. Если-же править образ диспетчера на диске (taskmgr.exe из папки system32), то это грязный способ и его модификацию может обнаружить системный механизм SFC (System Files Checker) - проверка целостности системных файлов и всякие гуарды. Так-что оптимальным вариантом будет поиск диспетчера в памяти, и инжект шела в его пространство.

будет какая нибудь статья про написание демосцен (ну работа с графикой и тд) ?
Когда-то интересовался демо/сценами, но то было под досом, и уже ничего не помню.
В реальном режиме выводил правда картинки BMP и даже писал для этого конвертор. А под виндой графикой не занимался. Предпочитаю хардкор в реальном режиме, где нет ничего, а только BIOS и порты - вот это руль и захватывает не по-детски.
 

Hardreversengineer

Green Team
20.08.2019
49
28
BIT
14
Обычно инжектят в память, а для этого процесс диспетчера должен быть запушен. Если-же править образ диспетчера на диске (taskmgr.exe из папки system32), то это грязный способ и его модификацию может обнаружить системный механизм SFC (System Files Checker) - проверка целостности системных файлов и всякие гуарды. Так-что оптимальным вариантом будет поиск диспетчера в памяти, и инжект шела в его пространство.


Когда-то интересовался демо/сценами, но то было под досом, и уже ничего не помню.
В реальном режиме выводил правда картинки BMP и даже писал для этого конвертор. А под виндой графикой не занимался. Предпочитаю хардкор в реальном режиме, где нет ничего, а только BIOS и порты - вот это руль и захватывает не по-детски.

Прикольно, а я пробовал делать на OpenGL. Но что-то у меня выходит сделать демку на 4кб. Вот если бы узнать вот какие то хитрости, методы определённые, то было бы классно.
Кстати, есть код (под DOS правда) :
Это 32байтная демка.
C-подобный:
;S equ 0B1h -
S equ 0E5h
org 100h

mov al,13h
int 10h
lds bx,[bx]

M:
cmp [bx],cl
adc [bx],ah
imul bx,S
mov cl,[bx]
add cl,[bx+di]
add cl,[bx-321]
add cl,[bx+si+63]
dec bx

in al,60h
dec al
jnz M
ret
 
  • Нравится
Реакции: Marylin

zelfix wrol

One Level
20.09.2019
3
2
BIT
0
Не посоветуете ли какую-нибудь документацию по сокетам на asm? Хотел попробовать заменить сокет на неблокирующий, но нахожу статьи только на c++ и т.д.
 

Hardreversengineer

Green Team
20.08.2019
49
28
BIT
14
Не посоветуете ли какую-нибудь документацию по сокетам на asm? Хотел попробовать заменить сокет на неблокирующий, но нахожу статьи только на c++ и т.д.

Как говорил мой преподаватель по инженерной графике: "Найдите десять отличий".
(троиточие - пропуск кода, остальное - это то, что требуется для реализации функции)
C++:
#include <winsock2.h>

...

int WSAStartup(
  WORD      wVersionRequired,
  LPWSADATA lpWSAData
);

и

C-подобный:
...

.data
wsa      WSADATA; значение WSADATA можно посмотреть в wsock32.inc который инклюдится ниже

...

invoke WSAStartup,0x0101,wsa ; инициализация WinSock

...

section '.idata' import data readable
library   wsock32,'wsock32.dll',\
...
include 'api\wsock32.inc'

То есть, как вы понимаете, это работает со всеми командами. Если же значений в функции много, а вам нужно заполнить лишь некоторые, перед invoke ставьте 'c' -> cinvoke.
 

Marylin

Mod.Assembler
Red Team
05.06.2019
305
1 375
BIT
315
но нахожу статьи только на c++
Лично я на асме по сокетам доков не встречал, и тоже разбирался на сишных примерах. Если определите проблему конкретней, то может вместе как-то осилим её. Кстати чтобы постоянно не рыскать по MSDN, имеется справочник по сокетам в формате CHM, на всякий цепляю его в скрепке, может кому пригодится.

Если же значений в функции много, а вам нужно заполнить лишь некоторые, перед invoke ставьте 'c' -> cinvoke.
Не совсем так..
invoke и cinvoke отличаются "соглашением о вызове" процедур и функций. В большей степени соглашение определяет то, кто именно будет очищать стек от аргументов на выходе из функции.

В первом случае - это классический __stdcall, когда стек очищает сама вызываемая функция. По такому соглашению работают все виндовые API.

Второй метод назвали __cdecl и это как-раз cinvoke, когда стек от аргументов очищает вызывающий. Если посмотреть в отладчике, то после "cinvoke" всегда идёт add esp, кол-во аргументов.
 

Вложения

  • sock2.zip
    330,4 КБ · Просмотры: 529

zelfix wrol

One Level
20.09.2019
3
2
BIT
0
Если определите проблему конкретней
Сканер открытых портов в примере работает 1 сек/порт, мне стало интересно оптимизировать его работу. Пока только увеличил скорость в 2 раза, добавив второй поток, основываясь на пример из статьи "(4.0) Системные механизмы Windows" (перебираю вторую половину портов в этом потоке). Есть идеи добавить массив потоков, массив сокетов в 1 потоке, заменить блокирующий сокет на неблокирующий, но для реализации пока что не хватает моих знаний в asm, вот я и попросил что-нибудь на подобие того справочника, который вы закрепили.
 
  • Нравится
Реакции: bin1101d и Marylin

Marylin

Mod.Assembler
Red Team
05.06.2019
305
1 375
BIT
315
заменить блокирующий сокет на неблокирующий,
Потоки это руль, а вот с неблокирующими сокетами есть детали..
Во-первых нужно понимать, при каких обстоятельствах сокет блокирует поток, и только потом использовать неблокирующие сокеты. Дело в том, что профита от неблокируемых мы можем и не получить, поскольку в некоторых ситуациях они выполняются абсолютно одинаково по времени:

1. connect - никогда не блокирует UDP-сокеты, зато практически всегда останавливает (блокирует) поток для TCP-соединений, т.к. в этом случае ей требуется время на установление связи с удалённым сокетом.​
2. recv - блокирует поток, только если на момент вызова буфер удалённого сокета пуст, т.е. нечего принимать.​
3. send - блокирует, если в буфере удалённого сокета недостаточно места, чтобы сбросить туда передаваемую информацию.​

Если применение неблокирующих принципиально, то сначала нужно перевести сокет в этот режим функцией ioctlsocket() с параметром FIONBIO =0x8004667E (аргумент =1), и дальше прослушивать состояние сокета функцией select(). К селект привязывается структура FD_SET (см.инклуд), в которой хранится массив дескрипторов прослушиваемых сокетов (можно прослушивать до 64 сокета):

C-подобный:
struct fd_set                   ;// для функции select()
   fd_count      dd  0            ; число сокетов в массиве
   fd_array      dd  64 dup(0)    ; массив сокетов
ends

Есть хорошая книга: Григорьев А.Б. "О чем не пишут в книгах по Delphi", где достаточно внятно объясняются детали работы с сокетами - советую обзавестись, тем-более что она лежит в свободном доступе.
 

Dez FromSRP01

New member
12.03.2020
1
0
BIT
0
Потоки это руль, а вот с неблокирующими сокетами есть детали..
Во-первых нужно понимать, при каких обстоятельствах сокет блокирует поток, и только потом использовать неблокирующие сокеты. Дело в том, что профита от неблокируемых мы можем и не получить, поскольку в некоторых ситуациях они выполняются абсолютно одинаково по времени:

1. connect - никогда не блокирует UDP-сокеты, зато практически всегда останавливает (блокирует) поток для TCP-соединений, т.к. в этом случае ей требуется время на установление связи с удалённым сокетом.​
2. recv - блокирует поток, только если на момент вызова буфер удалённого сокета пуст, т.е. нечего принимать.​
3. send - блокирует, если в буфере удалённого сокета недостаточно места, чтобы сбросить туда передаваемую информацию.​

Если применение неблокирующих принципиально, то сначала нужно перевести сокет в этот режим функцией ioctlsocket() с параметром FIONBIO =0x8004667E (аргумент =1), и дальше прослушивать состояние сокета функцией select(). К селект привязывается структура FD_SET (см.инклуд), в которой хранится массив дескрипторов прослушиваемых сокетов (можно прослушивать до 64 сокета):

C-подобный:
struct fd_set                   ;// для функции select()
   fd_count      dd  0            ; число сокетов в массиве
   fd_array      dd  64 dup(0)    ; массив сокетов
ends

Есть хорошая книга: Григорьев А.Б. "О чем не пишут в книгах по Delphi", где достаточно внятно объясняются детали работы с сокетами - советую обзавестись, тем-более что она лежит в свободном доступе.
Мощно, спасибо большое за инфу, а как заставить asm работать с http?
 

Hardreversengineer

Green Team
20.08.2019
49
28
BIT
14
Мощно, спасибо большое за инфу, а как заставить asm работать с http?
Автора долго нет в сети, по-этому постараюсь ответить я.
Во первых, посмотрите что такое GET и POST запросы и чем они отличаются. Потом, посмотрите следующую статью 5.2 WinSock протокол WHOIS, там очень хороший пример отправки POST-запроса. При этом, ничего трудного там нет, всё строится на вызовах из wsock32.dll, если присмотреться, то структура тоже не сложная: получить ip по имени, создать TCP-сокет, подключение, отправка, принятие, и вывод того что приняли на экран.
 

Marylin

Mod.Assembler
Red Team
05.06.2019
305
1 375
BIT
315
а как заставить asm работать с http?
можно конечно сокетами, только это нижний уровень.
есть ещё специальные функции из библиотеки Httpapi.dll
примеры реализации сервера можно найти на MSDN например
 
  • Нравится
Реакции: Mikl___

viktor plutt

Заблокирован
13.03.2020
17
3
BIT
0
На форуме приветствуется уважительное отношение к участникам. ПРЕДУПРЕЖДЕНИЕ!
можно конечно сокетами, только это нижний уровень.
есть ещё специальные функции из библиотеки Httpapi.dll
примеры реализации сервера можно найти на MSDN например

Похоже это пример для твоих друганов из LGBT :) А пример на асме не выложил - спиздить негде?
 

viktor plutt

Заблокирован
13.03.2020
17
3
BIT
0
Это второе предупреждение за хамское поведение. Аккаунт заблокирован бессрочно.
мерень... ты свой круг мне не навязывай,

Я один раз только и прочитал твою писанину , в которой ты с васма взял тул столетеней давности и пару картинок приклеил своих . Ееби мозги пионерам и кушай свою пионерскую славу :)
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!