VI. Заканчиваем план
Удалять открытие файла мне лень, поэтому пусть структура кода будет такой:
1) Открываем файл
2) Инициализируем WinSock
3) Подключаемся к Ya.ru (213.180.204.8)
4) Отправляем GET-запрос
“GET / HTTP/1.1”, CR, LF, “Host: ya.ru”, CR, LF, CR, LF.
5) Получаем данные
6) Сохраняем в файл
7) Закрываем WinSock
8) Закрываем файл
Итак, поехали!
1) Файл уже открыт. Надо либо удалить код с CloseHandle (выделяем -> пр. кнопка -> Binary -> Fill with 00’s), либо писать поверх – закрытый файл нам не нужен.
2) WSAStartup – это у нас «
CALL 00460512»
Параметры можно посмотреть вышеописанным способом, а можно вспомнить =)

Нам нужно найти место, где мы будем хранить
WSAData – то, что вернёт
WSAStartup (а версию сокетов я поставил
2, т.е.
2.0).
WSAData’у можно хранить в виртуальной памяти, не трогая место в файле. Поэтому смело указываем что-нибудь типа
461000 – это адрес внутри нашей секции, в которую мы можем писать данные, но он уже вне секции в файле, иначе говоря, этот адрес находится от начала секции на расстоянии, большем, чем её
RawSize. Хотя нам сама структура
WSAData как результат WSAStartup и не понадобится, но, если что, то она – там.
Можем проверить – трассируем программу (по F8) – и видим, что по адресу
461000 действительно что-то появилось. Кстати, если где-то в вашем коде – ошибка, а вы уже прошли то место, где она возникла, то всегда можно изменить текущую выполняемую инструкцию – выбираем интересующее нас место и нажимаем
Ctrl+”*” c NumPad'а (или
прав. кнопка -> New Origin Here).
3) Подключаемся к ya.ru.
Для этого нам нужно где-то хранить его IP-адрес, и хранить его мы должны, так сказать, в физическом месте файла, то есть он должен «влезть» в RawSize. Запишем его рядом с “a.txt” (в
460606):
А заодно нажмём Ctrl+A...
И в этот прекрасный момент мы понимаем, что забыли подгрузить функции
inet_addr, socket и closesocket... Ну, ничего, это поправимо! Сохраняем все уже сделанные в Оле изменения (конечно, только то, что нам нужно сохранить – нам не нужна полученная WSAData, да и места под неё в файле нет!) в файле
target_2.exe вышеописанным способом, закрываем Олю, закрываем LordPE и открываем его снова с target_2.exe, на этот раз – с правом на запись. Заходим в таблицу импорта, добавляем ещё одну группу импортов из
WS2_32.dll (да, ничего плохого в этом нет) с нужными функциями.
Наши
ThunkRVA – это
640C8, 640CC, 640D0. Закрываем лорда, он нам больше не понадобится, и открываем
target_2.exe в Оле. Идём в то место, где мы писали прыжки на внешние функции, и дописываем туда
jmp [4640C8] и т.п.
Для подключения нам нужно заполнить структуру
SockAddr (её описание можно без труда найти, я заполню её без лишних комментариев). Хранить её мы будем, к примеру, по адресу
461020. Она занимает 16 байт.
Запишем туда адрес сервера (он будет в
461020+4). Идём в начало кода, и вызываем оттуда
inet_addr с параметром – адресом строки с IP.
Полученное в eax значение сохраняем в
461024:
Код:
MOV DWORD PTR DS:[461024], EAX
Первые 2 байта структуры занимает WORD 2:
Код:
MOV WORD PTR DS:[ 461020], 2
Далее 2 байта – это
htons(80)=5000h, то есть порт.
Код:
MOV WORD PTR DS:[ 461022], 5000
Итак, структуру заполнили, осталось открыть сокет функцией
socket(AF_INET, SOCK_STREAM, IPPROTO_IP):
Код:
PUSH 0 // это - IPPROTO_IP
PUSH 1 // SOCK_STREAM
PUSH 2 // AF_INET
CALL 460536 //socket
Сохраним полученный в EAX сокет в 461040:
MOV DWORD PTR DS:[461040], EAX
Осталось подключиться с помощью connect’а:
PUSH 10 // те самые 16 байт – размер структуры
PUSH 461020 // адрес структуры
PUSH DWORD PTR DS:[461040] // тут лежит наш дескриптор сокета
CALL 460518 //connect
Мы подключились!
