Не много погуглив, перерыв весь этот форум (возможно упустил что-то), касаемо получения правильного адреса функции SendPacket. Теперь хочу поэкспериментировать над сие чудом, и что собственно скрывается за капотом.
Сразу скажу, что я не гуру и не знаток C++, перейдя с Delphi на C++ у меня есть какой-то опыт работы с типами данных. И я не прошу Вас писать что-то за меня.
Взятый пример из форума функции SendPacket для использования.
Код:
void hSendPck(unsigned int This, char* Format, ...) {
unsigned char buf[1024];
int size = 0, len;
wchar_t* wstr;
va_list args;
va_start(args, Format);
while (*Format != 0)
{
switch (*Format)
{
case 'c':
*(unsigned char*)(buf + size) = va_arg(args, unsigned char);
size++;
break;
case 'h':
*(unsigned short int*) (buf + size) = va_arg(args, unsigned short int);
size += 2;
break;
case 'd':
*(unsigned int*)(buf + size) = va_arg(args, unsigned int);
size += 4;
break;
case 'Q':
*(unsigned __int64*)(buf + size) = va_arg(args, unsigned __int64);
size += 8;
break;
case 'b':
len = va_arg(args, unsigned int);
memcpy(buf + size, va_arg(args, void*), len);
size += len;
break;
case 'S':
wstr = va_arg(args, wchar_t*);
if (wstr == 0)
{
len = 2;
*(unsigned short int*) (buf + size) = 0;
}
else
{
len = wcslen(wstr) * 2 + 2;
memcpy(buf + size, wstr, len);
}
size += len;
break;
}
Format++;
}
va_end(args);
return (*true_SendPacket)(This, "b", size, (int)buf);
}
пока ждем, что папки скажут... но у меня вопрос это получается ты посылаешь пакет путем использования какой-то функции? а напрямую сразу данные нельзя слать? типа выделяешь кусочек памяти, туда втуливаешь этот самый пакет как есть 2F 2B 05 00 00 00 00 00 00 00 и потом посылаешь.
пока ждем, что папки скажут... но у меня вопрос это получается ты посылаешь пакет путем использования какой-то функции? а напрямую сразу данные нельзя слать? типа выделяешь кусочек памяти, туда втуливаешь этот самый пакет как есть 2F 2B 05 00 00 00 00 00 00 00 и потом посылаешь.
Пакет как есть можно отправить функцией send() из стандартного набора WinSock, предварительно хукнув её. Вариант этот сразу отпадает из-за необходимости шифрования пакет(а/ов) с помощью Blowfish (XOR/RSA), а так же поиск ключа для шифрования.
Если открыть L2 через IDA и поставить бряки на функции из класса UNetworkHandler можно невооруженным глазом увидеть вызовы SendPacket. Получить адрес функции, затем из своего кода шаманить с ней.
Вопрос лишь в правильной структуре и формата пакета, чтобы его принял сервер или клиент.
Последний раз редактировалось 0day, 26.10.2020 в 13:51.
Elecktron, ну да, твой код конечно значительно проще, особенно если учесть:
- необходимость понимания ассемблера, чтобы разобраться с косяками
- могут быть исключения (как думаешь многие смогут понять почему и сам то сможешь ответить на этот вопрос?)
- могут быть исключения если в mask будет не 2 символа (тоже сильно сомневаюсь, что многие поймут почему)
- небольшая придирка: подходит для хроник GF+ (на C4 и IT не
сработает)
Жаль только, что в твоем коде на кой-то ляд используется регистр ESI и ему не восстанавливается его изначальное значение, что в некоторых случаях МОЖЕТ привести к исключению или ошибках в других частях программы. Вот именно поэтому и нужно знать ассемблер, чтобы не писать код с так называемым "непредсказуемым поведением".
И ассемблер полезно использовать там, где в нем есть необходимость, а не бездумно пихать куда попало (особенно если до конца не понимаешь как он работает), да и твой код прекрасно записывается на с++:
при этом в с++ варианте код реально рабочий, универсальный, не приводит к глупым ошибкам, когда у тебя меняется маска, да и явно выглядит попроще, неправда ли?