Тема: Сниффер
Показать сообщение отдельно
Старый 23.06.2010, 00:27   #74
user456
Новичок
 
Регистрация: 31.03.2010
Сообщений: 22
Сказал(а) спасибо: 2
Поблагодарили 23 раз(а) в 8 сообщениях
user456 На верном пути
По умолчанию

сама сборка пакетов (для пикапа тоже пригодится)
Код:
constructor TTcpBuffer.Create;
begin
    FCS:=TCriticalSection.Create;
    setlength(FSeqArr, SIZE64);
    FSeqCount:=0;
    FCurrSeq:=0;
    //FNextSeq:=0;
    FDupCount:=0;
    FOorCount:=0;
end;

destructor TTcpBuffer.Destroy;
var
   i: integer;
begin
    FCS.Enter;
    // |--[ack|array] count,first
    // |         |--[seq|wsabuf]
    // |         |--[seq|wsabuf]
    // |         |--[seq|wsabuf]
    for i:=0 to FSeqCount - 1 do
      FreeMem(FSeqArr[i].wsa_buf.buf);
    FSeqArr:=nil;
    FCS.Leave;
    FCS.Free;
    inherited;
end;

procedure TTcpBuffer.ASwap(Lo, Hi: integer);
var
   temp: TSeqRec;
begin
     move(FSeqArr[Lo],temp,sizeof(TSeqRec));
     move(FSeqArr[Hi],FSeqArr[Lo],sizeof(TSeqRec));
     move(temp,FSeqArr[Hi],sizeof(TSeqRec));
end;

procedure TTcpBuffer.QuickSort(iLo, iHi: integer);
var
  Lo, Hi: integer;
  pivot: dword;
begin
    Lo := iLo;
    Hi := iHi;
    pivot:=FSeqArr[(Lo + Hi) div 2].swappedSeq;
    repeat
      while FSeqArr[Lo].swappedSeq < pivot do Inc(Lo);
      while FSeqArr[Hi].swappedSeq > pivot do Dec(Hi);
      if Lo <= Hi then begin
        if Lo <> Hi then ASwap(Lo,Hi);
        Inc(Lo);
        Dec(Hi);
      end;
    until Lo > Hi;
    if Hi > iLo then QuickSort(iLo, Hi);
    if Lo < iHi then QuickSort(Lo, iHi);
end;

{function TTcpBuffer.QuickFind(const looking_for: dword; iLo, iHi: integer):dword;
var
  Mid: dword;
  pivot: dword;
begin
    if (iHi-iLo-1) > 0 then begin
       Mid:=(iLo+iHi) div 2;
       pivot:=FSeqArr[Mid].swappedSeq;
       if pivot < looking_for then result:=QuickFind(looking_for,Mid,iHi)
       else result:=QuickFind(looking_for,iLo,Mid);
    end
    else if looking_for > FSeqArr[iLo].swappedSeq then result:=iHi
    else result:=iLo;
end;}

function TTcpBuffer.Match(Value: dword; ItemIndex: integer): integer;
begin
    result:=0;
    if Value < FSeqArr[ItemIndex].swappedSeq then result:=-1
    else if Value > FSeqArr[ItemIndex].swappedSeq then result:=1;
end;

function TTcpBuffer.QuickSearch(Value: dword; Count: integer; MatchFunction: TMatchFunction): integer;
var
  L, M, C: integer;
begin
  if Count > 0 then
  begin
    L := 0;
    Dec(Count);
    while L <= Count do
    begin
      M := (L + Count) shr 1;
      C := MatchFunction(Value, M);
      if C > 0 then
        L := M + 1
      else if C <> 0 then
        Count := M - 1
      else
      begin
        Result := M;
        Exit;
      end;
    end;
  end;
  Result := -1;
end;

{ Add any match cap sequence to array }
procedure TTcpBuffer.Add2Buffer(data: pointer; swappedSeq,len,dataOffs: dword; isFromServer: boolean);
var
  prev: dword;
  dataLen: dword;
  i: integer;
begin
    prev:=FSeqCount;
    inc(FSeqCount);
    if FSeqCount > length(FSeqArr) then
      setlength(FSeqArr, ((length(FSeqArr) shr 6) + 1) shl 6); //by 64
    GetMem(FSeqArr[prev].wsa_buf.buf, len);
    move(data^, FSeqArr[prev].wsa_buf.buf^, len);
    FSeqArr[prev].wsa_buf.len:=len;
    FSeqArr[prev].swappedSeq:=swappedSeq;
    FSeqArr[prev].dataOffs:=dataOffs;
    dataLen:=len - dataOffs;
    FSeqArr[prev].dataLen:=dataLen;
    //if swappedSeq = FNextSeq then
    //  FNextSeq:=FCurrSeq + dataLen;
    if FSeqCount > 1 then
      QuickSort(0, FSeqCount - 1);
    if FSeqCount = 10 then begin
      if isFromServer then AddToLog('SMSG')
      else AddToLog('CMSG');
      AddToLog('current '+IntToHex(FCurrSeq,8)+' datalen '+IntToHex(dataLen,4));
      AddToLog('expecting '+IntToHex(FCurrSeq + dataLen,8));
      for i := 0 to 9 do AddToLog('seq['+IntToStr(i)+']='+IntToHex(FSeqArr[i].swappedSeq,8));
    end;
end;

{ Add any packet from current to current+MAX_DELTA_BROWSE_SEQUENCE }
procedure TTcpBuffer.AddData(data: pointer; len: dword; isFromServer: boolean);
var
   packetFlags: word;
   ipHdrLen,tcpHdrDataOffs,dataOffs: dword;
   pIpHdr: PIPHeader;
   pTcpHdr: PTCPHeader;
   pseudoHdr: TTCPPseudoHeader;
   pseudohdrCS,cs: word;
   swappedSeq,maxPossibleSeq: dword;
label fin;
begin
     FCS.Enter;
     pIpHdr:=PIPHeader(data);
     ipHdrLen:=GetIPHeaderLen(pIpHdr);
     pTcpHdr:=PTCPHeader(@TBytes(data)[ipHdrLen]);

     //check already in array
     swappedSeq:=ntohl(pTcpHdr.sequenceNumber);
     if FSeqCount > 1 then begin
        if QuickSearch(swappedSeq, FSeqCount, Match) >= 0 then begin
          //AddToLog(Format('skip duplicated seq: %.8x swseq: %.8x',[pTcpHdr.sequenceNumber,swappedSeq]));
          inc(FDupCount); goto fin;
        end;
     end
     else if FSeqCount > 0 then begin
        if FSeqArr[0].swappedSeq = swappedSeq then begin
          //AddToLog(Format('skip duplicated seq: %.8x swseq: %.8x',[pTcpHdr.sequenceNumber,swappedSeq]));
          inc(FDupCount); goto fin;
        end;
     end;
     //check CS
     cs:=GetChecksum(pIpHdr, ipHdrLen);
     if cs <> 0 then begin
        if isFromServer then AddToLog('wrong iphdr cs='+IntToHex(cs,4)+' src=server')
        else AddToLog('wrong iphdr cs='+IntToHex(cs,4)+' src=client');
        if (checkCS)and(isFromServer) then goto fin;
     end;
     if isFromServer then begin
        pseudoHdr.iph_src:=pIpHdr.iph_src;
        pseudoHdr.iph_dest:=pIpHdr.iph_dest;
        pseudoHdr.reserved:=0;
        pseudoHdr.iph_protocol:=pIpHdr.iph_protocol;
        pseudoHdr.tcp_length:=ntohs(len - ipHdrLen); //ntohl shr 16;
        pseudohdrCS:=not(GetChecksum(@pseudoHdr, sizeof(pseudoHdr)));
        cs:=GetChecksum(pTcpHdr, len - ipHdrLen, pseudohdrCS);
        if cs <> 0 then begin
          if isFromServer then AddToLog('wrong iphdr cs='+IntToHex(cs,4)+' src=server')
          else AddToLog('wrong iphdr cs='+IntToHex(cs,4)+' src=client');
          if (checkCS) then goto fin;
        end;
     end;

     packetFlags:=ntohs(pTcpHdr.flags);
     //initial sequences
     if (packetFlags and TCP_FLAG_SYN) <> 0 then begin
        //FNextSeq:=
        FCurrSeq:=swappedSeq + 1; //FNextSeq;
        goto fin;
     end;
     //if (packetFlags and TCP_FLAG_ACK) <> 0 then goto fin;
     maxPossibleSeq:=FCurrSeq + MAX_DELTA_BROWSE_SEQUENCE;
     if ((FCurrSeq < maxPossibleSeq)and((swappedSeq < FCurrSeq)or(swappedSeq > maxPossibleSeq))) //linear
        or ((FCurrSeq > maxPossibleSeq)and((swappedSeq < FCurrSeq)and(swappedSeq > maxPossibleSeq))) then begin
          //AddToLog(Format('skip out of range seq: %.8x swseq: %.8x FCurrSeq: %.8x',[pTcpHdr.sequenceNumber,swappedSeq,FCurrSeq]));
          inc(FOorCount); goto fin;
     end;
     tcpHdrDataOffs:=GetTCPDataOffset(@TBytes(data)[ipHdrLen]);
     dataOffs:=ipHdrLen+tcpHdrDataOffs;
     if len > dataOffs then     
        Add2Buffer(data, swappedSeq, len, dataOffs, isFromServer);
   fin:
     FCS.Leave;
end;

procedure TTcpBuffer.RemoveAt(seqArrPos: integer);
begin
    Assert(seqArrPos < FSeqCount);
    FreeMem(FSeqArr[seqArrPos].wsa_buf.buf);
    if seqArrPos < (FSeqCount - 1) then
      move(FSeqArr[seqArrPos+1], FSeqArr[seqArrPos], sizeof(TSeqRec)*(FSeqCount - seqArrPos - 1));
    dec(FSeqCount);
end;

procedure TTcpBuffer.Release(swappedSeq: dword);
var
  maxPossibleSeq: dword;
  i,spos: integer;
begin
    FCS.Enter;
    if FSeqCount > 1 then begin
       //AddToLog(Format('TTcpBuffer.Release seq: %.8x swseq: %.8x FSeqCount: %d',[bswap(swappedSeq),swappedSeq,FSeqCount]));
       //for i := 0 to FSeqCount - 1 do
       //  AddToLog(Format('FSeqArr[%d] swseq: %.8x wsa_buf.buf: %.8x wsa_buf.len: %d',[i,FSeqArr[i].swappedSeq,dword(FSeqArr[i].wsa_buf.buf),FSeqArr[i].wsa_buf.len]));

       spos:=QuickSearch(swappedSeq, FSeqCount, Match);
       if spos >= 0 then begin
         //AddToLog(Format('swseq found at %d',[spos]));
         FCurrSeq:=FCurrSeq + FSeqArr[spos].dataLen;
         RemoveAt(spos);
       end;
       //remove trash
       i:=0;
       while i < FSeqCount do begin
         maxPossibleSeq:=FCurrSeq + MAX_DELTA_BROWSE_SEQUENCE;
         if maxPossibleSeq > FCurrSeq then begin
           if (FSeqArr[i].swappedSeq < FCurrSeq)or(FSeqArr[i].swappedSeq > maxPossibleSeq) then begin
             //AddToLog(Format('FSeqCount: %d removing at: %d FCurrSeq: %.8x maxPossibleSeq: %.8x swseq: %.8x',[FSeqCount,i,FCurrSeq,maxPossibleSeq,FSeqArr[i].swappedSeq]));
             RemoveAt(i);
           end
           else inc(i);
         end
         else if (FSeqArr[i].swappedSeq < FCurrSeq)and(FSeqArr[i].swappedSeq > maxPossibleSeq) then begin
           //AddToLog(Format('FSeqCount: %d removing at: %d FCurrSeq: %.8x maxPossibleSeq: %.8x swseq: %.8x',[FSeqCount,i,FCurrSeq,maxPossibleSeq,FSeqArr[i].swappedSeq]));
           RemoveAt(i);
         end
         else inc(i);
       end;
    end
    else if FSeqCount > 0 then begin
       if FSeqArr[0].swappedSeq = swappedSeq then begin
         FCurrSeq:=FCurrSeq + FSeqArr[0].dataLen;
         RemoveAt(0);
       end;
    end;
    FCS.Leave;
end;

{ Get next matched sequence }
function TTcpBuffer.GetSequence: PSeqRec;
var
  spos: integer;
begin
    result:=nil;
    FCS.Enter;
    if FSeqCount > 1 then begin
       spos:=QuickSearch(FCurrSeq, FSeqCount, Match);
       if spos >= 0 then result:=@FSeqArr[spos];
    end
    else if FSeqCount > 0 then begin
       if FSeqArr[0].swappedSeq = FCurrSeq then
         result:=@FSeqArr[0];
    end;
    FCS.Leave;
end;
и вот тут были вопросы по самой организации обработки (если какой-то пакет не пришел то сколько надо хранить? не гигабайты же. Если потом пришел, но с него другие sequence пошли, то что? А приходили такие порой при глючной сети и жутких лагах). Потом описанная в никсах проверка контрольных сумм шла под ХР и нивкакую под вин7. Пришлось отказаться от проверки КС.
user456 вне форума   Ответить с цитированием
2 пользователя(ей) сказали cпасибо:
Konctantin (23.06.2010), zergtmn (23.06.2010)