Fritz! Box 7490: Cách tải lên tệp cấu hình đã sửa đổi


11

Tôi có một Fritz! Hộp 7490 DSL / Modem / Bộ định tuyến của AVM.

Người ta có thể kết xuất cấu hình hiện tại của bộ định tuyến dưới dạng tệp (trong "Hệ thống> Sao lưu> Tab Lưu"). Kết quả là một tệp văn bản có cấu trúc đơn giản, không phải JSON, nhưng gần như vậy (Quyết định thiết kế tuyệt vời, AVM!)

Tôi muốn sửa đổi nó một cách độc đáo và tải lên lại để thay đổi cấu hình của bộ định tuyến.

Tôi muốn sửa đổi điều gì? Đầu tiên, làm trống bộ đệm DHCP cực lớn hiện nay - thực hiện việc này thông qua giao diện mất nhiều thời gian (hàng giờ nhấp chuột). Thứ hai, sửa đổi các máy chủ DNS được chuyển đến các máy khách DHCP trên mạng LAN, các tùy chọn servercfg.user_dns1_for_ipv4servercfg.user_dns2_for_ipv4không thể truy cập qua giao diện 7490.

Tuy nhiên, tiện ích tải lên cấu hình của bộ định tuyến ("Hệ thống> Sao lưu> Tab khôi phục") xác minh tính toàn vẹn của tệp. Rõ ràng, nó tính toán tổng kiểm tra từ các nội dung và xác minh chúng so với tổng kiểm tra được nhúng trong tệp để tải lên. Đây là dòng sau đây ở cuối:

**** END OF EXPORT 0428BE3C ****

Nếu có sự không phù hợp, tải lên bị từ chối với "Tệp được chỉ định không phải là tệp nhập hợp lệ." (Nếu có sự trùng khớp, tải lên được áp dụng mà không cần phải quảng cáo thêm và bộ định tuyến được khởi động lại. Ouch!)

Trong mô hình 7390, người ta có thể vô hiệu hóa kiểm tra tính toàn vẹn bằng cách thêm NoChecks=yestrước chuỗi giới thiệu **** CFGFILE:ar7.cfgở trên cùng (ví dụ: Thay đổi DNS trên Fritzbox của bạn ) Điều này dường như không còn hoạt động trong 7490 (quá nhiều người làm hỏng thiết bị của họ?)

Có một cách giải quyết khác để làm cho phiên bản POKE hiện đại này hoạt động không?


Một đồng nghiệp đã thực sự tìm thấy một thuật toán tính toán tổng kiểm tra tại Fritz! Box VBScripte . Hmmmm ... thời gian để kiểm tra điều này (và viết lại thành Perl?)
David Tonhofer

Bạn có thể chấp nhận câu trả lời của riêng bạn.
peterh - Phục hồi Monica

Có thể đặt cài đặt bị UI từ chối không? Ví dụ: sử dụng toàn bộ không gian Unicode trong SSID?
nikeee

@nikeee Mình không có ý kiến. Hoàn toàn có thể.
David Tonhofer

Câu trả lời:


12

Đây là một tập lệnh dường như tính toán chính xác tổng kiểm tra, hóa ra là tổng kiểm tra CRC32. Cuối cùng, tôi đã không thành công trong việc xóa bộ đệm DHCP của Fritz! Box thông qua kết xuất / sửa đổi / khôi phục cấu hình. Thở dài.

#!/usr/bin/perl

# Read Fritz!Box configuration dump file and compute its checksum using CRC32.
# The problem is only knowing what to checksum exactly, and in this case its not pretty.
# Inspired from the very compact Visual Basic script by Michael Engelke available at
# http://www.mengelke.de/Projekte/FritzBoxVBScript 

# The Fritz!Box accepts a modified file where the checksum has been changed 
# manually to the output of this program in the last line. I have no idea what 
# happens if there is a syntax error anywhere inside the config file, so beware.

# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

use strict;
use warnings;

# ---
# Compute CRC start values
# ---

sub build_crc_table() {
   my @crctbl = (); # Accepts 256 values

   for (my $a = 0; $a < 256; $a++) {
      my $c = $a;
      for (my $b = 0; $b < 8; $b++) {
         my $d = $c & 0x01;
         $c = ($c >> 1) & 0x7FFFFFFF;
         if ($d) { 
            $c = $c ^ 0xEDB88320;
         }
      }
      push @crctbl, $c
   }

   my $print = 0;

   if ($print) {
      my $i = 0;
      foreach my $x (@crctbl) {
         print sprintf("CRC table value $i: %08x\n", $x);
         $i++
      }
   }

   return @crctbl
}

# ---
# Transform a string into a vector of its ASCII code points
# ---

sub numerize {
   my ($str) = @_;
   my @res = ();
   foreach my $ch (split('',$str)) {
      push @res, ord($ch)
   }
   return @res;
}

# ---
# Transform a hexstring into a vector of its 8-bit values
# ---

sub hexnumerize {
   my ($str) = @_;
   my @res = ();
   my $tmp;
   my $i = 0;
   foreach my $ch (split('',$str)) {
      if ($i == 0) { $tmp = $ch; $i++; }
      else         { $tmp.= $ch; $i=0; push @res,hex($tmp) } 
   }
   if ($i != 0) {
      die "Irregular hex string: $str\n";
   }
   return @res;
}

# ---
# Compute CRC-32 checksum
# See https://en.wikipedia.org/wiki/Cyclic_redundancy_check
# This must yield 414fa339:
# print sprintf("%08Xi\n", compute_crc32(numerize("The quick brown fox jumps over the lazy dog")));
# ---

sub compute_crc32 {
   my(@data)  = @_;
   my @crctbl = build_crc_table(); # not very efficient on multiple calls
   my $crc = 0xFFFFFFFF;
   my $i = 0;
   foreach my $x (@data) {
      my $index = ($crc ^ $x) & 0xFF;
      $crc = $crctbl[$index] ^ ($crc >> 8); # ">>" is zero-filling in Perl
      $crc = $crc & 0xFFFFFFFF;             # format to 32 bit
      #if ($i > 98700 && $i < 99000) {
      #   print sprintf("$i %c : $x => %08X\n",$x,$crc); 
      #}
      $i++
   }
   return $crc ^ 0xFFFFFFFF
}

# ---
# The name of the configuration file may have been given on the command line. 
# If so slurp the file.
# If nothing has been given, slurp STDIN.
# After that, the input can be found in "@lines" (line terminators are still in there)
# ---

my @lines;

if ($ARGV[0]) {
   open(my $fh,'<',$ARGV[0]) or die "Could not open file '$ARGV[0]': $!";
   @lines = <$fh>;
   close($fh)
}
else {
   @lines = <>;
}

# ---
# Stateful analysis.
# If there are lines after "END OF EXPORT" we will disregard them
# ---

my $firmware;       # will capture firmware version
my $fritzbox;       # will capture name string in header
my @data = ();      # will capture 8-bit values to be CRC-checksummed later
my $cursum;         # will capture the current CRC checksum in the text

# "state" indicates where we are in the file

my $state = 'NOTSTARTED';

# we consider the lines as a stack and push/pop to the stack

@lines = reverse @lines;

while (@lines && $state ne 'END') {

   my $line = pop @lines;

   if ($state eq 'NOTSTARTED') {
      if ($line =~ /^\*{4} (.*?) CONFIGURATION EXPORT/) {
         $fritzbox = $1;
         $state    = 'HEADER'
      }
      else {
         chomp $line;
         die "Expected 'CONFIGURATION EXPORT' in NOTSTARTED state, got '$line'"
      }
      next
   }

   if ($state eq 'HEADER') {
      chomp $line;
      if ($line =~ /(\w+)=([\w\$\.]+)$/) {
         my $key = $1;
         my $val = $2;
         if ($key eq 'FirmwareVersion') { $firmware = $val }
         push @data,numerize($key);
         push @data,numerize($val);
         push @data,0;
      }
      elsif ($line =~ /^\*{4}/) {
         $state = 'NEXTSECTION';
         push @lines,$line
      }
      else {
         die "Unexpected line in HEADER state: '$line'"
      }
      next
   }

   if ($state eq 'NEXTSECTION') {
      chomp $line;
      if ($line =~ /^\*{4} (?:CRYPTED)?(CFG|BIN)FILE:(\S+)/) {
         $state = "INSIDESECTION_$1";
         my $secname = $2;
         print "Section $line\n";
         push @data,numerize($secname);
         push @data,0
      }   
      elsif ($line =~ /^\*{4} END OF EXPORT (\w{8}) \*{4}/) {
         $state  = 'END';
         $cursum = $1
      }
      else {
          die "Unexpected line in NEXTSECTION state: '$line'"
      }
      next
   }

   if ($state eq 'INSIDESECTION_BIN') {
      chomp $line;
      if ($line =~ /^\*{4} END OF FILE \*{4}/) {
         $state = 'NEXTSECTION'
      } 
      else {
         push @data,hexnumerize($line)
      } 
      next
   }

   if ($state eq 'INSIDESECTION_CFG') {
      if ($line =~ /^\*{4} END OF FILE \*{4}/) {
         # Something unbelievably dirty: All section-internal linefeeds (and carriage returns)
         # are kept as is for checksumming, except for the last one before the "END OF FILE"
         if ($data[-1] == ord("\n")) {
            pop @data;
            if ($data[-1] == ord("\r")) {
               pop @data;
            }
         }
         $state = 'NEXTSECTION'
      }
      else {
         # More dirty stuff: Double backspaces are replaced by single ones for some reason.
         $line =~ s/\\\\/\\/g;
         push @data,numerize($line)
      }
      next
   } 

   die "Unexpected state $state"

}

if ($state ne 'END') {
   die 'Did not find proper end of configuration'
}
if (@lines) {
   my $n = @lines;
   print "There are still $n lines left that will be disregarded"
}

my $crc = compute_crc32(@data);
my $newsum = sprintf("%08X", $crc);

print "$fritzbox with firmware $firmware\n";

if ($newsum eq $cursum) {
   print "Checksum is OK: $cursum\n"
}
else {
   print "Found new checksum: $newsum\n";
   print "Checksum embedded in file is $cursum\n"
}

1
Đã kiểm tra tập lệnh với Fritz! Box 7390 của tôi và có thể tải lên cấu hình đã sửa đổi.
thiên hà

công cụ tuyệt vời! xác nhận (như galaxy hiện) nó vẫn hoạt động trên 7390. Phần sụn của tôi: 6.30 :)
Madivad

3
Kiểm tra phiên bản python (bao gồm win32 exe gui dựng sẵn) tại github.com/mementum/fritzchecksum
mementum

1
@David thực sự tốt đẹp, cảm ơn bạn rất nhiều. Tôi có thể xác nhận rằng điều này đang hoạt động trên LAB-BETA hiện tại (6.69) của F! Box 7490
Kev Inski
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.