Raw Socket для посылки UDP
Пользователи, просматривающие топик: none
|
Зашли как: Guest
|
Имя |
Сообщение |
<< Старые топики Новые топики >> |
|
|
Raw Socket для посылки UDP - 2007-12-24 09:49:08.730000
|
|
|
KX
Сообщений: 3
Оценки: 0
Присоединился: 2007-12-24 09:46:11.230000
|
Пытаюсь реализовать Raw Socket для посылки UDP на Delphi. (к слову сказать в валяющихся в инете примерах таких сокетов допущены ошибки, примеры не рабочие). Вроде всё получается. Формирую RAW IP сокет, формирую IP и UDP заголовки. Пакеты нормально уходят, а на получателе приходят! Но когда пытаюсь "подделать" пакет, а именно src_addr указать не свой, а поддельный, то пакет никуда не уходит, получатель его не получает. Подскажите в чём может быть дело. Фаерволы естественно отключены. Вообще говоря на машине, на которой подделываю заголовок, даже снифер не регистрирует исходящих пакетов. Но возможно просто снифер кривой.
|
|
|
RE: Raw Socket для посылки UDP - 2007-12-25 07:09:13.966666
|
|
|
Alaget
Сообщений: 330
Оценки: 0
Присоединился: 2007-11-08 15:57:53.170000
|
Я же не экстрасенс, скорей всего ты облажался, давай исходник, может и реабилитируешся.
|
|
|
RE: Raw Socket для посылки UDP - 2007-12-25 08:08:45.350000
|
|
|
KX
Сообщений: 3
Оценки: 0
Присоединился: 2007-12-24 09:46:11.230000
|
вот исходник
unit rawsocks;
interface
uses WinSock2,windows;
procedure UDPRaw(srcip:string;srcport:word;dstip:string;dstport:word;adata:PByte;data_length:integer);
implementation
type
ip_header=packed record
version:byte; // номер версии протокола
tos:byte; // тип сервиса
length:word; // общая длина пакета
id:word; // идентификатор пакета
flags:word; // флаги
ttl:byte; // Время жизни пакета
proto:byte; // Протокол верхнего уровня
crc:word; // CRC заголовка
src_addr:cardinal; // IP- адрес отправителя
dst_addr:cardinal; // IP- адрес получателя
end;
udp_header=packed record
src_port:word; // номер порта отправителя
dst_port:word; // номер порта получателя
length:word; // длина датаграммы
crc:word; // контрольная сумма заголовка
end;
pseudo_header=packed record
src_addr:cardinal; // адрес отправителя
dst_addr:cardinal; // адрес получателя
zero:byte; //начальная установка
proto:byte; // протокол
length:word; // длина заголовка
end;
function rs_crc(buffer:Pword;length:integer):word;
var
crc:longword;
begin
crc:= 0;
// Вычисление CRC
while (length > 1)do
begin
crc:=crc+buffer^;inc(buffer);
length:=length-sizeof(word);
end;
if(length<>0)then crc:=crc+ PByte(buffer)^;
// Закончить вычисления
crc:=(crc shr 16)+(crc and $ffff);
crc:=crc+(crc shr 16);
//возвращаем инвертированное значение CRC
result:=word(not crc);
end;
function rs_pseudo_crc(data:PByte;data_length:integer;src_addr:cardinal;
dst_addr:cardinal;packet_length:integer;proto:byte):word;
var
buffer:PByte;
full_length:cardinal;
header_length:byte;
ph:pseudo_header;
p_crc:word;
pdata:pByte;
begin
p_crc:=0;
// Заполнение структуры псевдозаголовка
ph.src_addr:=src_addr;
ph.dst_addr:=dst_addr;
ph.zero:=0;
ph.proto:=proto;
ph.length:=htons(packet_length);
header_length:=sizeof(pseudo_header);
full_length:=header_length + data_length;
getmem(buffer,full_length);fillchar(buffer^,full_length,0);
// Генерация псевдозаголовка
move(ph,buffer^,header_length);
pdata:=buffer;inc(pdata,header_length);move(data^,pdata^,data_length);
// Вычисление CRC.
p_crc:=rs_crc(PWord(buffer),full_length);
freemem(buffer,full_length);
result:=p_crc;
end;
function rs_init(v_major:integer;v_minor:integer):boolean;
var
wsadata:TWSAdata;
begin
result:=false;
// Инициализация WinSock заданной версии
if (WSAStartup(MAKEWORD(v_major, v_minor), wsadata)<>0)then exit;
// Проверка версии WinSock
if (LOBYTE(wsadata.wVersion) <> v_minor)or(HIBYTE(wsadata.wVersion) <> v_major)then
begin
WSACleanup;
exit;
end;
result:=true;
end;
function rs_send_ip (s:TSocket;iph:ip_header;data:Pbyte;
data_length:integer;dst_port_raw:word):integer;
var
buffer:PByte;
target:TSockAddrIn ;
header_length:byte;
packet_length:cardinal;
pdata:PByte;
begin
fillchar(target,sizeof(target),0);
target.sin_family:=AF_INET;
target.sin_addr.s_addr:=iph.dst_addr;
target.sin_port:=dst_port_raw;
// Вычисление длины и заголовка пакета
header_length:=sizeof(ip_header);
packet_length:=header_length+data_length;
// Установка CRC.
iph.crc:=0;
// Заполнение некоторых полей заголовка IP .
iph.version:=4*16+trunc(header_length/4);
// Если длина пакета не задана , то
//длина пакета приравнивается к длине заголовка
if (iph.length=0)then iph.length:=htons(packet_length);
getmem(buffer,packet_length);fillchar(buffer^,packet_length,0);
// Копирование заголовка пакета в буфер ( CRC равно 0).
move(iph,buffer^,sizeof(ip_header));
// Копирование данных в буфер
if(data<>nil)then
begin
pdata:=buffer;inc(pdata,header_length);move(data^,pdata^,data_length);
end;
// Вычисление CRC.
iph.crc:=rs_crc(PWord(buffer),packet_length);
// Копирование заголовка пакета в буфер ( CRC посчитана).
move(iph,buffer^,sizeof(ip_header));
// Отправка IP пакета в сеть.
result:=sendto(s,buffer^,packet_length,0,target,sizeof(target));
freemem(buffer,packet_length);
end;
function rs_send_udp (s:TSocket;iph:ip_header;udph:udp_header;
data:Pbyte;data_length:integer):integer;
var
buffer:PByte;
header_length:byte;
packet_length:cardinal;
pdata:PByte;
begin
//вычисление длин пакета и заголовка.
header_length:=sizeof(udp_header);
packet_length:=header_length+data_length;
// Установка CRC.
udph.crc:=0;
// Если длина пакета не задана , то
//длина пакета приравнивается к длине заголовка
if(udph.length=0)then udph.length:=htons(packet_length);
getmem(buffer,packet_length);fillchar(buffer^,packet_length,0);
// Копирование заголовка пакета в буфер ( CRC равно 0).
move(udph,buffer^,sizeof(udp_header));
// Копирование протокола более высокого уровня (данных)
if (data<>nil)then
begin
pdata:=buffer;inc(pdata,header_length);move(data^,pdata^,data_length);
end;
// Вычисление CRC.
udph.crc:=rs_pseudo_crc(buffer,packet_length,iph.src_addr,
iph.dst_addr,packet_length,IPPROTO_UDP);
// Копирование заголовка пакета в буфер ( CRC посчитана).
move(udph,buffer^,sizeof(udp_header));
// Отправка IP пакета со вложенным UDP пакетом.
result:=rs_send_ip(s,iph,buffer,packet_length,udph.dst_port);
freemem(buffer,packet_length);
end;
procedure UDPRaw(srcip:string;srcport:word;dstip:string;dstport:word;adata:PByte;data_length:integer);
var
iph:ip_header;
udph:udp_header;
s:TSocket;
tos:integer;
use_own_header:cardinal;
begin
//заполняем заголовок UDP пакета
iph.version:=$04;
iph.length:=0;//если в 0, то посчитается автоматом далее
iph.id:=0;
iph.ttl:=15;
iph.flags:=0;
iph.src_addr:=inet_addr(PChar(srcip));
iph.dst_addr:=inet_addr(PChar(dstip));
// Создание пустого буфера для данных.
s:= WSASocket(AF_INET,SOCK_RAW,IPPROTO_RAW,nil,0,WSA_FLAG_OVERLAPPED);
tos:=0;
setsockopt(s,IPPROTO_IP,3,PChar(@tos),sizeof(tos));
use_own_header:=1;
setsockopt(s,IPPROTO_IP,2,PChar(@use_own_header),sizeof(use_own_header));
iph.proto:=IPPROTO_UDP;
udph.src_port:=srcport;
udph.dst_port:=dstport;
//отправляем UDP пакет
if(data_length>0)then rs_send_udp (s, iph, udph, adata, data_length)
else rs_send_udp (s, iph, udph, nil, 0);
closesocket(s);
end;
end.
но когда в качестве исходящего адреса ставлю свой - всё уходит. тестил в ethernet сети. мне кажется дело не в коде, а в том, что нужно например ещё подменять мак, или ещё что то не учёл.
|
|
|
RE: Raw Socket для посылки UDP - 2007-12-26 13:35:18.183333
|
|
|
necrostaz
Сообщений: 172
Оценки: 0
Присоединился: 2007-02-27 15:54:59.460000
|
если стоит XP SP 2 или что-нить постарше, то подделать src_addr не получится, т.к. они эту лавочку в сырых сокетах прикрыли чтоб пресечь Ip-spoof на корню….так что сырые сокеты в винде не такие уж и сырые….выход есть - юзать WinPcap или что нить подобное
|
|
|
|
|