┌───────────────────────┐ ▄▄▄▄▄ ▄▄▄▄▄ ▄▄▄▄▄ │ │ █ █ █ █ █ █ │ │ █ █ █ █ █▀▀▀▀ │ │ █ █ █ █ ▄ │ │ ▄▄▄▄▄ │ │ █ █ │ │ █ █ │ │ █▄▄▄█ │ │ ▄ ▄ │ │ █ █ │ │ █ █ │ │ █▄▄▄█ │ │ ▄▄▄▄▄ │ │ █ │ in-memory-only fd-less ELF execution (with Perl) │ █ │ ~ isra _replace_this_by_@ fastmail.net └───────────────────█ ──┘ ====[ motivation ]============================================================== Approaches for in-memory-only ELF execution[1] typically use memfd_create() and fexecve() syscalls which rely on the existence of file descriptors in the /proc filesystem. This behaviour can be monitored and detected without much effort[2]. Therefore, the following questions arise: Is it possible to achieve in-memory-only ELF execution without using file descriptors? If so, can it be done using the default toolset of a common Linux distribution (i.e. without installing additional tools)? The answer is yes, thanks to Perl's standard modules and a bit of peek & poke. This article will describe the implementation of exec_elf64.pl, a script for in-memory-only ELF execution without touching the filesystem. This approach has the following considerations: - The ELF's binary content is hardcoded into the script's source code. - The ELF is parsed and loaded into memory. - The loading process supports relocations and use of external symbols from shared objects. In this case, external symbols are loaded from glibc. - Supports x64 ELFs. - The script is written in Perl, an interpreted language available by default on most Linux x64 distributions. Version 5.008001 or higher is required. Full source code can be found at: https://git.sr.ht/~hckng/elf/tree/master/item/exec_elf64.pl https://github.com/ilv/elf/blob/main/exec_elf64.pl ====[ preliminaries ]===================================================== The steps for loading and executing an ELF in memory can be summarized as follows: 1) Read ELF's binary content. 2) Parse ELF's headers (sections, segments, etc). 3) Use headers information to map ELF code and data into memory. 4) Apply relocations (including external symbols). 5) Execute ELF's mapped functions. Each of these steps will be discussed in the next sections, considering the following ELF object: ------------------------------ START obj.c ------------------------------------- #includevoid print_japh(void) { putchar('j'); putchar('a'); putchar('p'); putchar('h'); putchar('\n'); } int main(void) { char *str = "i am an elf"; printf("%s\n", str); print_japh(); return 0; } ------------------------------- END obj.c -------------------------------------- $ gcc -c obj.c $ file obj.o obj.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped ====[ part 1: read ELF ]======================================================== The usual approach for opening a file and perform I/O operations on it (such as read, write, seek, etc.) is by specifying a path to an existing file on the filesystem or by specifying a file descriptor, which in some cases may represent an "anonymous" or memory-only file[1]. These options require interaction with the regular filesystem and proc filesystem respectively. However, Perl provides an alternative method to open a filehandle by using a reference to a scalar variable instead of a filename. Consider the following: -------------------------------------------------------------------------------- my $buff; my $str = "hello world"; open my $fh, '<', \$str; read $fh, $buff, 5; close $fh; print "content read: $buff\n"; -------------------------------------------------------------------------------- The above code creates a filehandle $fh using a reference to the string $str and successfully reads 5 bytes into $buff by using the read() function. This method can also be applied to open the contents of an ELF object from a string reference and perform I/O operations on it. First, the read_elf() subroutine is defined as follows: -------------------------------------------------------------------------------- sub read_elf { my $code = get_code(); open my $fh, '<:raw', \$code; return ($code, $fh); } -------------------------------------------------------------------------------- The string $code and the filehandle $fh are returned since both will be used later during the parsing and mapping processes. To create the string $code the following perl one-liner is used: $ perl -e 'print"my \$code = \"\";\n";$/=\32;' \ -e 'print"\$code .= pack q/H*/, q/".(unpack"H*")."/;\n" while(<>)' ./obj.o The command above generates a string $code that contains the binary data of the ELF object. The string $code can then be included in the get_code() subroutine: -------------------------------------------------------------------------------- sub get_code { my $code = ""; $code .= pack q/H*/, q/7f454c460201010000000000[...]000000000000000000000/; $code .= pack q/H*/, q/000000000000000018040000[...]40000000040000d000c00/; $code .= pack q/H*/, q/554889e5bf6a000000e80000[...]f6000bf70000000e80000/; $code .= pack q/H*/, q/0000bf68000000e800000000[...]00000e3554889e54883ec/; [...] [...] $code .= pack q/H*/, q/000000000000000000000000[...]000006100000000000000/; $code .= pack q/H*/, q/000000000000000001000000[...]000000000000000000/; return $code; } -------------------------------------------------------------------------------- For simplicity, the get_code() subroutine is defined at the end of the exec_elf64.pl script to make it easy to replace the string $code by a new one. ====[ part 2: parse ELF ]======================================================= Perl does not provide an standard module for parsing ELFs. However, the unpack() function can be used to extract the ELF's binary content based on a set of fixed data templates[3]: - "C", an unsigned char value (1 byte). - "a", a string with arbitrary binary data (1 byte). - "x", a null byte. - "S", an unsigned short value (2 bytes). - "i", a signed integer value (4 bytes). - "I", an unsigned integer value (4 bytes). - "q", a signed quad value (8 bytes). - "Q", An unsigned quad value (8 bytes). The ELF header, section header table, symbol table, string table and relocations are parsed based mostly on the Linux referenced specifications[4][5][6][7] and the logic implemented in readelf.pl[8]. For the purpose of this work, two auxiliary subroutines ru() and mk_hash() are defined for reading/unpacking data and for creating hashes associated to the parsed headers, respectively. Then, the initial ELF header is read and parsed as follows (using the field names defined in @e_keys): -------------------------------------------------------------------------------- # elf header keys my @e_keys = ( 'ei_mag0', 'ei_mag1', 'ei_mag2', 'ei_mag3', 'ei_class', 'ei_data', 'ei_version', 'ei_osabi', 'ei_abiversion', #ei_pad ignored 'e_type', 'e_machine', 'e_version', 'e_entry', 'e_phoff', 'e_shoff', 'e_flags', 'e_ehsize', 'e_phentsize', 'e_phnum', 'e_shentsize', 'e_shnum', 'e_shstrndx' ); [...] sub parse_ehdr { my @hdr = ru($efh, "C a a a C C C C C x7 S S I q q q I S S S S S S", 0x40); mk_hash(\%ehdr, \@e_keys, \@hdr); } -------------------------------------------------------------------------------- In this case the ELF header is stored in %ehdr and its values can be accessed by using their corresponding field names (e.g. $ehdr{'ei_mag0'}). The program header table information is not used throughout the parsing and mapping processes and therefore is skipped. Next, the section header table is read and parsed as follows: -------------------------------------------------------------------------------- sub parse_shtab { seek $efh, $ehdr{'e_shoff'}, "SEEK_SET"; for (my $i = 0; $i < $ehdr{'e_shnum'}; $i++) { my %sh; my @hdr = ru($efh, "I I q q q q I I q q", $ehdr{'e_shentsize'}); mk_hash(\%sh, \@sh_keys, \@hdr); push @shtab, \%sh; # read content of section header entry of type 'STRTAB' if($sh{'sh_type'} == 3) { my $tmpstr; my $curr_offset = tell $efh; seek $efh, $sh{'sh_offset'}, "SEEK_SET"; read $efh, $tmpstr, $sh{'sh_size'}; seek $efh, $curr_offset, "SEEK_SET"; $strtab{$sh{'sh_offset'}} = $tmpstr; } } } -------------------------------------------------------------------------------- In the above code the section header table is represented by the @shtab array and its entries are represented as hashes based on the field names defined in the @sh_keys array. Additionally, when a section header table entry of sh_type = 3 (STRTAB) is found, the $efh filehandle position is set to its sh_offset for reading the entry's content and store it in %strtab, the hash that represents the string table. The section header table is parsed a second time to retrieve the name of each entry based on the contents of the string table. The indexes for the text, data, symtab, rodata and rela.text sections (in @shtab) are stored for direct access to such sections later in the parsing and mapping processes. -------------------------------------------------------------------------------- sub secname { my $ndx = shift; my $str = shift; my $s = substr($str, $ndx); my $r = substr($s, 0, index($s, "\0")); } # parse section names from string table sub parse_secnames { my $shstrtab = $shtab[$ehdr{'e_shstrndx'}]; for(my $i = 0; $i < $ehdr{'e_shnum'}; $i++) { my $name = secname( $shtab[$i]{'sh_name'}, $strtab{$shstrtab->{'sh_offset'}} ); # add 'name' to each section header entry $shtab[$i]{'name'} = $name; # save indexes for easier access to relevant segments $text_ndx = $i if($name eq '.text'); $data_ndx = $i if($name eq '.data'); $symtab_ndx = $i if($name eq '.symtab'); $rodata_ndx = $i if($name eq '.rodata'); $relatext_ndx = $i if($name eq '.rela.text'); } } -------------------------------------------------------------------------------- Next, the symbol table is read and parsed as follows: -------------------------------------------------------------------------------- # parse symbol table [...] my $symtab = $shtab[$symtab_ndx]; my $sh_link = $shtab[$symtab->{'sh_link'}]; my $num_entry = $symtab->{'sh_size'}/$symtab->{'sh_entsize'}; [...] seek $efh, $symtab->{'sh_offset'}, "SEEK_SET"; for (my $i = 0; $i < $num_entry; $i++) { my %sym; my @hdr = ru($efh, "I C C S q q", $symtab->{'sh_entsize'}); mk_hash(\%sym, \@st_keys, \@hdr); my $type = $sym{'st_info'} & 0x0f; my $name = secname( $sym{'st_name'}, $strtab{$sh_link->{'sh_offset'}} ); # add 'name' to each symbol $sym{'name'} = $name; push @symtab, \%sym; # save st_value of symbols of type 'FUNC' $funcs{$name} = $sym{'st_value'} if($type == 2); } -------------------------------------------------------------------------------- The symbol table is represented by the @symtab array and its entries are represented as hashes based on the field names defined in the @st_keys array, with an extra field "name" that represents the symbol's name obtained from the string table. Additionally, the %funcs hash is used to store the st_value of a function based on its name. Relocations are read and parsed in a similar way: -------------------------------------------------------------------------------- # parse relocations my $rt = $shtab[$relatext_ndx]; my $entry_num = $rt->{'sh_size'}/$rt->{'sh_entsize'}; [..] for (my $i = 0; $i < $entry_num; $i++) { my %r; my @hdr = ru($efh, "q Q i", $rt->{'sh_entsize'}); mk_hash(\%r, \@r_keys, \@hdr); # 4 bytes on little endian order my $sym_ndx = unpack("V", pack("N", $r{'r_info'} >> 8)); # low-order bits only my $type = $r{'r_info'} & 0x0f; my $sym_name = $symtab[$sym_ndx]{'name'}; my $sym_shndx = $symtab[$sym_ndx]{'st_shndx'}; $r{'type'} = $type; $r{'symndx'} = $sym_ndx; push @relocs, \%r; # save external symbols (st_shndx of type 'UND') # the num_extsym counter is used later for lookup in a 'jump table' $extsym{$sym_name} = $num_extsym++ if($sym_shndx == 0); } -------------------------------------------------------------------------------- In this case, the relocations are represented by the @relocs array and its entries are represented as hashes based on the field names defined in the @r_keys array, with two extra fields "type" and "symndx" that represent the relocation type and the index in the symbol table of the symbol associated to the relocation entry. The hash %extsym is used as well to keep track of the number of external symbols and their names. Finally, parse_elf() subroutine is defined as follows: -------------------------------------------------------------------------------- sub parse_elf { my $fh = shift; $efh = $fh; parse_ehdr(); parse_shtab(); parse_secnames(); parse_symtab(); parse_relocs(); } -------------------------------------------------------------------------------- ====[ part 3: map ELF ]========================================================= Most of the mapping process is based on [9] which consists basically in three steps: i) Memory mapping ii) Copying data into mapped area iii) Memory access protection i) Memory mapping Memory mapping can be achieved by using Perl's syscall() to call mmap: -------------------------------------------------------------------------------- my $ptr = syscall(9, $addr, $size, $protect, $flags, -1, 0); -------------------------------------------------------------------------------- Where: - 9 is the number of the mmap syscall in Linux x86_64. - $addr is the starting address for the new mapping. If 0, mmap will choose a suitable address and return it. - $size is the size of the mapping. - $protect is an integer that indicates the memory protection of the mapping. Possible values can be checked at [10]. In this case the value PROT_READ | PROT_WRITE = 3 is used. - $flags is an integer that indicates visibility of mapping changes and the use of files. In this case the value MAP_SHARED | MAP_ANONYMOUS = 33 is used. The remaining parameters are related to file mapping and can be ignored by using the values -1 and 0. mmap will return the starting address of the mapped area on success and -1 on failure. ii) Copying data into mapped area Unlike mmap, there is no syscall for copying data into memory. There is also no built-in function in Perl for copying raw data into memory. However, there are some memory tricks that can be used to that end: peek & poke. The code used for peek & poke is from [11], a script for syscall/shellcode injection in OSX, which allows to copy arbitrary data $bytes into a memory address $location of choice. (NOTE: some comments and checks were redacted for simplicity; the remaining comments are from the original author) -------------------------------------------------------------------------------- sub _pack_address { my $p = pack("Q", $_[0]); return $p; } sub peek { unpack "P$_[1]", _pack_address($_[0]); } sub poke { my($location, $bytes) = @_; my $len = length($bytes); my $addr = _pack_address($location); # construct a B::PV object, backed by a SV/SvPV to a dummy string # length($bytes) long, and substitute $location as the actual string storage # we specifically use the same length so we do not have to deal with resizing my $dummy = 'X' x $len; my $dummy_addr = \$dummy + 0; my $ghost_sv_contents = peek($dummy_addr, 8 + 4 + 4 + $Config{ivsize}); substr( $ghost_sv_contents, 8 + 4 + 4, 8 ) = $addr; my $ghost_string_ref = bless( \ unpack( "Q", # it is crucial to create a copy of $sv_contents, and work with a temporary # memory location. Otherwise perl memory allocation will kick in and wreak # considerable havoc culminating with an inevitable segfault do { no warnings 'pack'; pack( 'P', $ghost_sv_contents.'' ) }, ), 'B::PV' )->object_2svref; # now when we write to the newly created "string" we are actually writing # to $location eval 'substr($$ghost_string_ref, 0, $len) = $bytes'; return $len; } -------------------------------------------------------------------------------- In short, poke() modifies Perl's internal data types to force the creation of a temporary variable pointing to a string located at $location and then change the string's content with $bytes. To have a better understanding of how poke() works it's necessary to dig deeper into advanced concepts of Perl internals, which is beyond the scope of this article. The reader can check [12][13] for more information. iii) Memory access protection Similar to memory mapping, Perl's syscall() is used to call mprotect: -------------------------------------------------------------------------------- my $mp = syscall(10, $addr, $size, $protect); -------------------------------------------------------------------------------- Where: - 10 is the number of the mprotect syscall in Linux x86_64. - $addr an $size define the interval of the mapping area where access protections will be updated. - $protect is an integer that indicates the memory protection[14] for the specified interval. In this case the values PROT_READ | PROT_EXEC = 5 and PROT_READ = 1 are used. mprotect will return 0 on success and -1 on failure. The mapping process can now be done following the steps described on [9]. First, the ELF object code is mapped and its content copied into the mapped area. -------------------------------------------------------------------------------- $base_ptr = mmap(0, length($code), 3, 33); if($base_ptr == -1) { print "Failed to allocate memory for ELF\n"; exit; } poke($base_ptr, $code, length($code)); -------------------------------------------------------------------------------- Then the text, data, and rodata segments are mapped and copied into memory next to each other, along with an auxiliary jump table (described later). Given that the $code variable is a string that contains the binary content of the ELF object (as discussed in part 1), the content of each segment can be obtained by extracting a substring of $code based on their sh_offset and sh_size values. -------------------------------------------------------------------------------- my $text = $shtab[$text_ndx]; my $data = $shtab[$data_ndx]; my $rodata = $shtab[$rodata_ndx]; my $jmptab_size = $num_extsym*14; my $text_ptr = mmap( 0, page_align($text->{'sh_size'}) + page_align($data->{'sh_size'}) + page_align($rodata->{'sh_size'}) + page_align($jmptab_size), 3, 33 ); if ($text_ptr == -1) { print "Failed to allocate memory for .text\n"; exit; } my $data_ptr = $text_ptr + page_align($text->{'sh_size'}); my $rodata_ptr = $data_ptr + page_align($data->{'sh_size'}); my $jmptab_ptr = $rodata_ptr + page_align($rodata->{'sh_size'}); # copy segments into memory poke( $text_ptr, substr($code, $text->{'sh_offset'}, $text->{'sh_size'}) ); poke( $data_ptr, substr($code, $data->{'sh_offset'}, $data->{'sh_size'}) ); poke( $rodata_ptr, substr($code, $rodata->{'sh_offset'}, $rodata->{'sh_size'}) ); -------------------------------------------------------------------------------- After this the relocations are applied and the memory access protections are set for the text segment, rodata segment and jump table. -------------------------------------------------------------------------------- do_relocs($text_ptr, $data_ptr, $rodata_ptr, $jmptab_ptr); if(mprotect($text_ptr, $text->{'sh_size'}, 5) == -1) { print "Failed to mprotect .text\n"; exit; } # check .rodata sh_size fist in case is not defined if(exists $rodata->{'sh_size'}) { if(mprotect($rodata_ptr, $rodata->{'sh_size'}, 1) == -1) { print "Failed to mprotect .rodata\n"; exit; } } if(mprotect($jmptab_ptr, $jmptab_size, 5) == -1) { print "Failed to mprotect jump table\n"; exit; } -------------------------------------------------------------------------------- ====[ part 4: relocations and external symbols ]================================ Similar to the mapping process, relocations are performed following the steps described in [15] which only considers relocations of type R_X86_64_PLT32 = 4 and R_X86_64_PC32 = 2 for the text, data and rodata segments. Once again, the use of poke() allows copying the calculated relocation address into the original patch offset address. -------------------------------------------------------------------------------- my $sym_ndx = $relocs[$i]{'symndx'}; [...] my $patch_offset = $text_ptr + $relocs[$i]{'r_offset'}; $base_ptr = $text_ptr if($sec_name eq '.text'); $base_ptr = $data_ptr if($sec_name eq '.data'); $base_ptr = $rodata_ptr if($sec_name eq '.rodata'); $sym_addr = $base_ptr + $symtab[$sym_ndx]{'st_value'}; [...] if($relocs[$i]{'type'} == 4 or $relocs[$i]{'type'} == 2) { my $relo = $sym_addr + $relocs[$i]{'r_addend'} - $patch_offset; # pack in little endian order (4 bytes) $relo = pack("V", $relo); # apply relocation by simply copying the calculated address # into the patch offset address poke($patch_offset, $relo, length($relo)); } -------------------------------------------------------------------------------- External symbols, identified by having st_shndx = 0 (UND), are handled during the relocation process following the steps described in [16]. To achieve that, a simplified PLT/GOT is implemented by using an auxiliary jump table to resolve external references. Each entry in the jump table contains: - The address of the external symbol (8 bytes). - A fixed jump instruction "\xff\x25\xf2\xff\xff\xff" (6 bytes). For simplicity, the jump table is implemented by mapping N*14 bytes after the rodata segment and each entry on the jump table starts at position i*14, where 'N' is the number of external symbols and 'i' is a value between 0 and N-1 that represents the i-th external symbol found during the parsing process. -------------------------------------------------------------------------------- sub map_elf { [...] my $jmptab_size = $num_extsym*14; # map segments and 'jump table' next to each other my $text_ptr = mmap( 0, page_align($text->{'sh_size'}) + page_align($data->{'sh_size'}) + page_align($rodata->{'sh_size'}) + page_align($jmptab_size), 3, 33 ); [...] my $jmptab_ptr = $rodata_ptr + page_align($rodata->{'sh_size'}); [...] } -------------------------------------------------------------------------------- Given that the jump table is close enough in memory to the rest of the sections, the relocation for an external symbol must be calculated against the fixed jump instruction in its jump table's entry, which performs a backwards jump (-14 bytes) to the start of the entry, where the actual address of the external symbol is stored. -------------------------------------------------------------------------------- my $sym_ndx = $relocs[$i]{'symndx'}; [...] my $sym_name = $symtab[$sym_ndx]{'name'}; [...] my $jmptab_ndx = $jmptab_ptr + ($extsym{$sym_name}*14); $sym_addr = $jmptab_ndx + 8; -------------------------------------------------------------------------------- The external symbol address can be obtained by using Perl's DynaLoader standard module that "Dynamically load C libraries into Perl code"[17]. First, a library reference for looking up the symbol must be loaded with dl_load_file(). In this case the glibc shared object is used: -------------------------------------------------------------------------------- my $libc_path = "/usr/lib/x86_64-linux-gnu/libc.so.6"; my $libref = DynaLoader::dl_load_file($libc_path, 0x01); -------------------------------------------------------------------------------- The external symbol address is looked up using dl_find_symbol() with the library reference and the symbol's name as parameters. The jump table entry is then built by packing the external address in little-endian order and appending the jump instruction. Finally, the jump table entry is copied into memory at the position $jmptab_ndx calculated before. After this the relocation process is resumed using $jmptab_ndx + 8 as the symbol address for the relocation formula. -------------------------------------------------------------------------------- my $jmptab_ndx = $jmptab_ptr + ($extsym{$sym_name}*14); $sym_addr = $jmptab_ndx + 8; [...] my $ext_addr = DynaLoader::dl_find_symbol($libref, $sym_name); # "V" format is 4 bytes; external address is 8 bytes my ($p1, $p2) = unpack("V2", pack("Q", $ext_addr)); my $jmptab_entry = pack("V", $p1); $jmptab_entry .= pack("V", $p2); $jmptab_entry .= "\xff\x25\xf2\xff\xff\xff"; # update 'jump table' in memory poke($jmptab_ndx, $jmptab_entry, length($jmptab_entry)); [...] my $relo = $sym_addr + $relocs[$i]{'r_addend'} - $patch_offset; -------------------------------------------------------------------------------- ====[ part 5: execute ELF ]===================================================== Perl's DynaLoader standard module is used once again to execute the ELF's mapped functions. In addition to loading external libraries and finding symbols, DynaLoader can install "external subroutines" by using dl_install_xsub(): -------------------------------------------------------------------------------- my $ref = dl_install_xsub($perl_name, $symref [, $filename]) -------------------------------------------------------------------------------- This method creates a new Perl external subroutine named $perl_name using $symref as a pointer to the function which implements the routine. On success, dl_install_xsub() returns a reference to the "installed function". According to the DynaLoader documentation: "It must be stressed that the DynaLoader, by itself, is practically useless for accessing non-Perl libraries because it provides almost no Perl-to-C 'glue'. There is, for example, no mechanism for calling a C library function or supplying arguments" However, it is possible to use dl_install_xsub() providing the st_value of an ELF's mapped function as pointer and successfully achieve execution. -------------------------------------------------------------------------------- sub exec_func { my $func_name = shift; my $text_ptr = shift; my $func_ptr = $funcs{$func_name}; my $func = DynaLoader::dl_install_xsub( "_japh", # not really used $text_ptr + $func_ptr, __FILE__ # no file ); # dereference and execute &{$func}; } -------------------------------------------------------------------------------- In this case the name of the function to be executed is "main". Finally, the main logic of the script can be reduced to: -------------------------------------------------------------------------------- my ($code, $fh) = read_elf(); parse_elf($fh); my $text_ptr = map_elf($code); exec_func('main', $text_ptr); -------------------------------------------------------------------------------- And then: $ perl exec_elf64.pl i am an elf japh ====[ after math ]============================================================= To achieve complete fd-less execution, one option is encoding the script's source code in base64 on a remote host, decode it on the target machine and then pipe it to the perl interpreter: # on a remote host $ cat exec_elf64.pl | base64 --wrap 0 IyEvdXNyL2Jpbi9wZXJsCgp1c2UgRHluYU[...........................................] [.............................................................................] [.............................................................................] [.............................................................................] ByZXR1cm4gJGNvZGU7Cn0= # on the target machine $ echo "IyEvdXNyL2Jpbi9wZX[...]ByZXR1cm4gJGNvZGU7Cn0=" | base64 -d | perl i am an elf japh On the other hand, to make it easier to test and debug exec_elf64.pl with other ELFs objects the read_elf() subroutine can be adapted to open regular files as follows: -------------------------------------------------------------------------------- sub read_elf { # uncomment below to open ELF as a regular file my $in = pop (@ARGV); my $code = ""; open my $fh, '<:raw', $in; $code .= $_ while(<$fh>); close $fh; open my $fh, '<:raw', $in; #my $code = get_code(); #open my $fh, '<:raw', \$code; return ($code, $fh); } -------------------------------------------------------------------------------- For completeness an additional test is performed with a more elaborated ELF, in this case, the "self-mutating x86_64 C program"[18] which implements self-mutating code to spawn a /bin/sh shell: $ gcc -c selfmut.c $ ps o user,cmd USER CMD isra /bin/bash isra ps o user,cmd $ perl exec_elf64.pl selfmut.o Calling foo i: 1 Calling foo $ ps o user,cmd USER CMD isra /bin/bash isra /bin/sh isra ps o user,cmd ====[ extra mile ]============================================================= The original script for syscall/shellcode injection in OSX[11] can be easily adapted for Linux x64 by using the mmap() and mprotect() subroutines described in part 3, achieving assembly code execution with the use of DynaLoader and peek & poke. Consider the following code: ---------------------------- BEGIN code.s -------------------------------------- BITS 64 global _start section .text _start: call main db "i am a shellcode", 0xa, 0x0 main: xor rax, rax xor rdx, rdx inc al mov rdi, rax pop rsi mov dl, 17 syscall xor rdx, rdx mov rax, 60 syscall ------------------------------- END code.s ------------------------------------- $ nasm -f elf64 code.s -o code.o $ objdump -d code.o Then, using the hexadecimal representation of the text section of code.o: -------------------------------------------------------------------------------- my $code = "\xe8\x12\x00\x00\x00\x69\x20\x61\x6d\x20\x61\x20\x73\x68\x65\x6c"; $code .= "\x6c\x63\x6f\x64\x65\x0a\x00\x48\x31\xc0\x48\x31\xd2\xfe\xc0\x48"; $code .= "\x89\xc7\x5e\xb2\x11\x0f\x05\x48\x31\xd2\xb8\x3c\x00\x00\x00\x0f"; $code .= "\x05"; my $p = mmap(0, length($code), 3, 33); if($p == -1) { print "Couldn't mmap!\n"; exit; } poke($p, $code, length($code)); if(mprotect($p, length($code), 5) == -1) { print "Failed to mprotect\n"; exit; } my $func = DynaLoader::dl_install_xsub("_shell", $p, __FILE__); &{$func}; ------------------------------ END CODE ---------------------------------------- $ perl exec_asm.pl i am a shellcode Which can also be executed fd-less by using the approach mentioned before (base64 encoding and decoding). ====[ references ]============================================================= [1] https://magisterquis.github.io/2018/03/31/in-memory-only-elf-execution.html [2] https://sandflysecurity.com/blog/detecting-linux-memfd-create-fileless-malware-with-command-line-forensics/ [3] https://perldoc.perl.org/functions/pack [4] https://refspecs.linuxfoundation.org/elf/gabi4+/ch4.eheader.html [5] https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html [6] https://refspecs.linuxbase.org/elf/gabi4+/ch4.symtab.html [7] https://refspecs.linuxbase.org/elf/gabi4+/ch4.reloc.html [8] https://github.com/lampmanyao/readelf/blob/master/readelf.pl [9] https://blog.cloudflare.com/how-to-execute-an-object-file-part-1/ [10] https://man7.org/linux/man-pages/man2/mmap.2.html [11] https://gist.github.com/monoxgas/c0b0f086fc7aa057a8256b42c66761c8 [12] https://perldoc.perl.org/perlguts [13] https://awarenetwork.org/etc/aware.ezine.1.alpha.txt [14] https://man7.org/linux/man-pages/man2/mprotect.2.html [15] https://blog.cloudflare.com/how-to-execute-an-object-file-part-2/ [16] https://blog.cloudflare.com/how-to-execute-an-object-file-part-3/ [17] https://perldoc.perl.org/DynaLoader [18] https://shanetully.com/2013/12/writing-a-self-mutating-x86_64-c-program/ ====[ source code ]============================================================= IyEvdXNyL2Jpbi9wZXJsCiMgZXhlY19lbGY2NC5wbAojIHdyaXR0ZW4gYnkgaXNyYSAtIGlzcmEg X3JlcGxhY2VfYnlfQF8gZmFzdG1haWwubmV0IC0gaHR0cHM6Ly9oY2tuZy5vcmcKIwojIGh0dHBz Oi8vZ2l0LnNyLmh0L35oY2tuZy9lbGYvdHJlZS9tYXN0ZXIvaXRlbS9leGVjX2VsZjY0LnBsCiMg aHR0cHM6Ly9naXRodWIuY29tL2lsdi9lbGYvYmxvYi9tYWluL2V4ZWNfZWxmNjQucGwKIyAKIyB2 ZXJzaW9uIDAuMSAtIDIwMjMKIwojIGluLW1lbW9yeS1vbmx5IGZkLWxlc3MgRUxGIGV4ZWN1dGlv bjoKIwojICAtIHJlYWQsIHBhcnNlLCBtYXAsIGFuZCBleGVjdXRlIGEgaGFyZGNvZGVkIEVMRiB4 NjQgb2JqZWN0CiMgIC0gc3VwcG9ydHMgcmVsb2NhdGlvbiBhbmQgZXh0ZXJuYWwgc3ltYm9scyAo ZnJvbSBnbGliYykKIyAgLSB1c2VzIFBlcmwgdjUuMDA4MDAxIG9yIGhpZ2hlcgojICAtIG9ubHkg c3RhbmRhcmQgbW9kdWxlcyBhcmUgdXNlZAojCiMgdG8gcnVuOgojICAgICAkIHBlcmwgZXhlY19l bGY2NC5wbAojCiMgb3IgKGZ1bGwgZmQtbGVzcyk6CiMgICAgICQgZWNobyBCQVNFNjRfRU5DT0RF RF9DT05URU5UIHwgYmFzZTY0IC1kIHwgcGVybAojCiMgdGhhbmtzIHRvIHRtcDB1dCBhbmQgdnh1 ZyBmb3IgYWxsIHRoZSByZXNvdXJjZXMKIwoKCnVzZSBEeW5hTG9hZGVyOwojdXNlIERldmVsOjpQ ZWVrOwp1c2UgNS4wMDgwMDE7ICMgYmVjYXVzZSA1LjYgZG9lc24ndCBoYXZlIEI6OlBWOjpvYmpl Y3RfMnN2cmVmCnVzZSBDb25maWc7CnVzZSBCICgpOyAjIGZvciBCOjpQVgp1c2Ugc3RyaWN0OwoK CiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyByZWFkIGVsZgojIyMjIyMjIyMjIyMjIyMjIyMjIyMj IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj CgpzdWIgcmVhZF9lbGYgewogICAgIyB1bmNvbW1lbnQgYmVsb3cgdG8gb3BlbiBFTEYgYXMgYSBy ZWd1bGFyIGZpbGUKICAgICNteSAkaW4gPSBwb3AgKEBBUkdWKTsKICAgICNteSAkY29kZSA9ICIi OwoKICAgICNvcGVuIG15ICRmaCwgJzw6cmF3JywgJGluOwogICAgIyRjb2RlIC49ICRfIHdoaWxl KDwkZmg+KTsKICAgICNjbG9zZSAkZmg7CgogICAgI29wZW4gbXkgJGZoLCAnPDpyYXcnLCAkaW47 CgogICAgbXkgJGNvZGUgPSBnZXRfY29kZSgpOwogICAgb3BlbiBteSAkZmgsICc8OnJhdycsIFwk Y29kZTsKCiAgICByZXR1cm4gKCRjb2RlLCAkZmgpOwp9CgoKIyMjIyMjIyMjIyMjIyMjIyMjIyMj IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj IwojIHBhcnNlIGVsZiB4NjQKIyByZWZlcmVuY2U6IGh0dHBzOi8vZ2l0aHViLmNvbS9sYW1wbWFu eWFvL3JlYWRlbGYvYmxvYi9tYXN0ZXIvcmVhZGVsZi5wbAojIyMjIyMjIyMjIyMjIyMjIyMjIyMj IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj CgojIyMjIyMjIGdsb2JhbCB2YXJpYWJsZXMgIyMjIyMjIwoKIyBhcnJheXMgZm9yIHNlY3Rpb24g aGVhZGVyIHRhYmxlLCBzeW1ib2wgaGVhZGVyIHRhYmxlLCByZWxvY2F0aW9ucwpteSAoQHNodGFi LCBAc3ltdGFiLCBAcmVsb2NzKTsKIyBoYXNoZXMgZm9yIGVsZiBoZWFkZXIsIHN0cmluZyB0YWJs ZSwgZXh0ZXJuYWwgc3ltYm9scywgZnVuY3Rpb25zCm15ICglZWhkciwgJXN0cnRhYiwgJWV4dHN5 bSwgJWZ1bmNzKTsKCiMgaW5kZXhlcyBmb3IgcmVsZXZhbnQgc2VnbWVudHMgb24gdGhlIHNlY3Rp b24gaGVhZGVyIHRhYmxlCm15ICgkdGV4dF9uZHgsICRkYXRhX25keCwgJHJvZGF0YV9uZHgsICRz eW10YWJfbmR4LCAkcmVsYXRleHRfbmR4KTsKCiMgbnVtYmVyIG9mIGV4dGVybmFsIHN5bWJvbHMK bXkgJG51bV9leHRzeW0gPSAwOwoKIyBzaGFyZWQgbGlicmFyeSB0byBsb29rdXAgZXh0ZXJuYWwg c3ltYm9scwojIG9ubHkgZ2xpYmMgZm9yIG5vdwpteSAkbGliY19wYXRoID0gIi91c3IvbGliL3g4 Nl82NC1saW51eC1nbnUvbGliYy5zby42IjsKbXkgJGxpYnJlZiA9IER5bmFMb2FkZXI6OmRsX2xv YWRfZmlsZSgkbGliY19wYXRoLCAweDAxKTsKCiMgZWxmIGZpbGUgaGFuZGxlcgpteSAkZWZoOwoK IyMjIyMjIyBrZXlzIGZvciByZWxldmFudCBoYXNoZXMgIyMjIyMjIwoKIyBlbGYgaGVhZGVyIGtl eXMKbXkgQGVfa2V5cyA9ICgKICAgICdlaV9tYWcwJywgJ2VpX21hZzEnLCAnZWlfbWFnMicsICdl aV9tYWczJywgJ2VpX2NsYXNzJywgJ2VpX2RhdGEnLCAKICAgICdlaV92ZXJzaW9uJywgJ2VpX29z YWJpJywgJ2VpX2FiaXZlcnNpb24nLCAjZWlfcGFkIGlnbm9yZWQKICAgICdlX3R5cGUnLCAnZV9t YWNoaW5lJywgJ2VfdmVyc2lvbicsICdlX2VudHJ5JywgJ2VfcGhvZmYnLCAnZV9zaG9mZicsCiAg ICAnZV9mbGFncycsICdlX2Voc2l6ZScsICdlX3BoZW50c2l6ZScsICdlX3BobnVtJywgJ2Vfc2hl bnRzaXplJywgJ2Vfc2hudW0nLAogICAgJ2Vfc2hzdHJuZHgnCik7CgojIHNlY3Rpb24gaGVhZGVy IGtleXMKbXkgQHNoX2tleXMgPSAoCiAgICAnc2hfbmFtZScsICdzaF90eXBlJywgJ3NoX2ZsYWdz JywgJ3NoX2FkZHInLCAnc2hfb2Zmc2V0JywgJ3NoX3NpemUnLAogICAgJ3NoX2xpbmsnLCAnc2hf aW5mbycsICdzaF9hZGRyYWxpZ24nLCAnc2hfZW50c2l6ZScKKTsKCiMgc3ltYm9sIHRhYmxlIGtl eXMKbXkgQHN0X2tleXMgPSAoCiAgICAnc3RfbmFtZScsICdzdF9pbmZvJywgJ3N0X290aGVyJywg J3N0X3NobmR4JywgJ3N0X3ZhbHVlJywgJ3N0X3NpemUnCik7CgojIHJlbG9jYXRpb25zIGtleXMK bXkgQHJfa2V5cyA9ICgncl9vZmZzZXQnLCAncl9pbmZvJywgJ3JfYWRkZW5kJyk7CgoKIyMjIyMj IyBhdXhpbGlhcnkgc3Vicm91dGluZXMgIyMjIyMjIwoKIyByZWFkICYgdW5wYWNrIGJpbmFyeSBj b250ZW50CnN1YiBydSB7CiAgICBteSAkZmggID0gc2hpZnQ7CiAgICBteSAkdHBsID0gc2hpZnQ7 CiAgICBteSAkc3ogID0gc2hpZnQ7CgogICAgcmVhZCAkZmgsIG15ICRidWZmLCAkc3o7CiAgICBy ZXR1cm4gdW5wYWNrKCR0cGwsICRidWZmKTsKfQoKIyBtYWtlIGhhc2ggdG8gZWFzaWx5IGhhbmRs ZSB2YXJpb3VzIGhlYWRlcnMgCnN1YiBta19oYXNoIHsKICAgIG15ICRoYXNocmVmID0gc2hpZnQ7 CiAgICBteSAka2V5c3JlZiA9IHNoaWZ0OwogICAgbXkgJHZhbHNyZWYgPSBzaGlmdDsKCiAgICBm b3IobXkgJGkgPSAwOyAkaSA8IEB7JGtleXNyZWZ9OyAkaSsrKSB7CiAgICAgICAgJGhhc2hyZWYt Pnska2V5c3JlZi0+WyRpXX0gPSAkdmFsc3JlZi0+WyRpXTsKICAgIH0KfQoKIyBwYXJzZSBlbGYg aGVhZGVyCiMgc2VlIGh0dHBzOi8vcmVmc3BlY3MubGludXhmb3VuZGF0aW9uLm9yZy9lbGYvZ2Fi aTQrL2NoNC5laGVhZGVyLmh0bWwKc3ViIHBhcnNlX2VoZHIgewogICAgbXkgQGhkciA9IHJ1KCRl ZmgsICJDIGEgYSBhIEMgQyBDIEMgQyB4NyBTIFMgSSBxIHEgcSBJIFMgUyBTIFMgUyBTIiwgMHg0 MCk7CiAgICBta19oYXNoKFwlZWhkciwgXEBlX2tleXMsIFxAaGRyKTsKfQoKIyBwYXJzZSBzZWN0 aW9uIGhlYWRlciB0YWJsZQojIHNlZSBodHRwczovL3JlZnNwZWNzLmxpbnV4YmFzZS5vcmcvZWxm L2dhYmk0Ky9jaDQuc2hlYWRlci5odG1sCnN1YiBwYXJzZV9zaHRhYiB7CiAgICBzZWVrICRlZmgs ICRlaGRyeydlX3Nob2ZmJ30sICJTRUVLX1NFVCI7IAogICAgZm9yIChteSAkaSA9IDA7ICRpIDwg JGVoZHJ7J2Vfc2hudW0nfTsgJGkrKykgewogICAgICAgIG15ICVzaDsKICAgICAgICBteSBAaGRy ID0gcnUoJGVmaCwgIkkgSSBxIHEgcSBxIEkgSSBxIHEiLCAkZWhkcnsnZV9zaGVudHNpemUnfSk7 CiAgICAgICAgbWtfaGFzaChcJXNoLCBcQHNoX2tleXMsIFxAaGRyKTsKICAgICAgICBwdXNoIEBz aHRhYiwgXCVzaDsKCiAgICAgICAgIyByZWFkIGNvbnRlbnQgb2Ygc2VjdGlvbiBoZWFkZXIgZW50 cnkgb2YgdHlwZSAnU1RSVEFCJwogICAgICAgIGlmKCRzaHsnc2hfdHlwZSd9ID09IDMpIHsKICAg ICAgICAgICAgbXkgJHRtcHN0cjsKICAgICAgICAgICAgbXkgJGN1cnJfb2Zmc2V0ID0gdGVsbCAk ZWZoOwogICAgICAgICAgICBzZWVrICRlZmgsICRzaHsnc2hfb2Zmc2V0J30sICJTRUVLX1NFVCI7 CiAgICAgICAgICAgIHJlYWQgJGVmaCwgJHRtcHN0ciwgJHNoeydzaF9zaXplJ307CiAgICAgICAg ICAgIHNlZWsgJGVmaCwgJGN1cnJfb2Zmc2V0LCAiU0VFS19TRVQiOwogICAgICAgICAgICAkc3Ry dGFieyRzaHsnc2hfb2Zmc2V0J319ID0gJHRtcHN0cjsKICAgICAgICB9CiAgICB9Cn0KCiMgZ2V0 IHNlY3Rpb24gbmFtZQpzdWIgc2VjbmFtZSB7CiAgICBteSAkbmR4ID0gc2hpZnQ7CiAgICBteSAk c3RyID0gc2hpZnQ7CgogICAgbXkgJHMgPSBzdWJzdHIoJHN0ciwgJG5keCk7CiAgICBteSAkciA9 IHN1YnN0cigkcywgMCwgaW5kZXgoJHMsICJcMCIpKTsKfQoKIyBwYXJzZSBzZWN0aW9uIG5hbWVz IGZyb20gc3RyaW5nIHRhYmxlCnN1YiBwYXJzZV9zZWNuYW1lcyB7CiAgICBteSAkc2hzdHJ0YWIg PSAkc2h0YWJbJGVoZHJ7J2Vfc2hzdHJuZHgnfV07CiAgICBmb3IobXkgJGkgPSAwOyAkaSA8ICRl aGRyeydlX3NobnVtJ307ICRpKyspIHsKICAgICAgICBteSAkbmFtZSA9IHNlY25hbWUoCiAgICAg ICAgICAgICRzaHRhYlskaV17J3NoX25hbWUnfSwgCiAgICAgICAgICAgICRzdHJ0YWJ7JHNoc3Ry dGFiLT57J3NoX29mZnNldCd9fQogICAgICAgICk7CiAgICAgICAgIyBhZGQgJ25hbWUnIHRvIGVh Y2ggc2VjdGlvbiBoZWFkZXIgZW50cnkKICAgICAgICAkc2h0YWJbJGldeyduYW1lJ30gPSAkbmFt ZTsKCiAgICAgICAgIyBzYXZlIGluZGV4ZXMgZm9yIGVhc2llciBhY2Nlc3MgdG8gcmVsZXZhbnQg c2VnbWVudHMKICAgICAgICAkdGV4dF9uZHggICAgICAgPSAkaSBpZigkbmFtZSBlcSAnLnRleHQn KTsKICAgICAgICAkZGF0YV9uZHggICAgICAgPSAkaSBpZigkbmFtZSBlcSAnLmRhdGEnKTsKICAg ICAgICAkc3ltdGFiX25keCAgICAgPSAkaSBpZigkbmFtZSBlcSAnLnN5bXRhYicpOwogICAgICAg ICRyb2RhdGFfbmR4ICAgICA9ICRpIGlmKCRuYW1lIGVxICcucm9kYXRhJyk7CiAgICAgICAgJHJl bGF0ZXh0X25keCAgID0gJGkgaWYoJG5hbWUgZXEgJy5yZWxhLnRleHQnKTsKICAgIH0KfQoKIyBw YXJzZSBzeW1ib2wgdGFibGUKIyBzZWUgaHR0cHM6Ly9yZWZzcGVjcy5saW51eGJhc2Uub3JnL2Vs Zi9nYWJpNCsvY2g0LnN5bXRhYi5odG1sCnN1YiBwYXJzZV9zeW10YWIgewogICAgbXkgJHN5bXRh YiAgICAgID0gJHNodGFiWyRzeW10YWJfbmR4XTsKICAgIG15ICRzaF9saW5rICAgICA9ICRzaHRh Ylskc3ltdGFiLT57J3NoX2xpbmsnfV07CiAgICBteSAkbnVtX2VudHJ5ICAgPSAkc3ltdGFiLT57 J3NoX3NpemUnfS8kc3ltdGFiLT57J3NoX2VudHNpemUnfTsKCiAgICBteSAkY3Vycl9maWxlX29m ZnNldCA9IHRlbGwgJGVmaDsKICAgIHNlZWsgJGVmaCwgJHN5bXRhYi0+eydzaF9vZmZzZXQnfSwg IlNFRUtfU0VUIjsKICAgIGZvciAobXkgJGkgPSAwOyAkaSA8ICRudW1fZW50cnk7ICRpKyspIHsK ICAgICAgICBteSAlc3ltOwogICAgICAgIG15IEBoZHIgPSBydSgkZWZoLCAiSSBDIEMgUyBxIHEi LCAkc3ltdGFiLT57J3NoX2VudHNpemUnfSk7CiAgICAgICAgbWtfaGFzaChcJXN5bSwgXEBzdF9r ZXlzLCBcQGhkcik7CgogICAgICAgIG15ICR0eXBlID0gJHN5bXsnc3RfaW5mbyd9ICYgMHgwZjsK ICAgICAgICBteSAkbmFtZSA9IHNlY25hbWUoCiAgICAgICAgICAgICRzeW17J3N0X25hbWUnfSwg CiAgICAgICAgICAgICRzdHJ0YWJ7JHNoX2xpbmstPnsnc2hfb2Zmc2V0J319CiAgICAgICAgKTsK ICAgICAgICAjIGFkZCAnbmFtZScgdG8gZWFjaCBzeW1ib2wgCiAgICAgICAgJHN5bXsnbmFtZSd9 ID0gJG5hbWU7CiAgICAgICAgcHVzaCBAc3ltdGFiLCBcJXN5bTsKCiAgICAgICAgIyBzYXZlIHN0 X3ZhbHVlIG9mIHN5bWJvbHMgb2YgdHlwZSAnRlVOQycKICAgICAgICAkZnVuY3N7JG5hbWV9ID0g JHN5bXsnc3RfdmFsdWUnfSBpZigkdHlwZSA9PSAyKTsKICAgIH0KICAgIHNlZWsgJGVmaCwgJGN1 cnJfZmlsZV9vZmZzZXQsICJTRUVLX1NFVCI7Cn0KCiMgcGFyc2UgcmVsb2NhdGlvbnMKIyBzZWUg aHR0cHM6Ly9yZWZzcGVjcy5saW51eGJhc2Uub3JnL2VsZi9nYWJpNCsvY2g0LnJlbG9jLmh0bWwK c3ViIHBhcnNlX3JlbG9jcyB7CiAgICBteSAkcnQgPSAkc2h0YWJbJHJlbGF0ZXh0X25keF07CiAg ICBteSAkZW50cnlfbnVtID0gJHJ0LT57J3NoX3NpemUnfS8kcnQtPnsnc2hfZW50c2l6ZSd9OwoK ICAgIG15ICRjdXJyX2ZpbGVfb2Zmc2V0ID0gdGVsbCAkZWZoOwogICAgc2VlayAkZWZoLCAkcnQt Pnsnc2hfb2Zmc2V0J30sICJTRUVLX1NFVCI7CiAgICBmb3IgKG15ICRpID0gMDsgJGkgPCAkZW50 cnlfbnVtOyAkaSsrKSB7CiAgICAgICAgbXkgJXI7CiAgICAgICAgbXkgQGhkciA9IHJ1KCRlZmgs ICJxIFEgaSIsICRydC0+eydzaF9lbnRzaXplJ30pOwogICAgICAgIG1rX2hhc2goXCVyLCBcQHJf a2V5cywgXEBoZHIpOwoKICAgICAgICAjIDQgYnl0ZXMgb24gbGl0dGxlIGVuZGlhbiBvcmRlciAK ICAgICAgICBteSAkc3ltX25keCA9IHVucGFjaygiViIsIHBhY2soIk4iLCAkcnsncl9pbmZvJ30g Pj4gOCkpOwogICAgICAgICMgbG93LW9yZGVyIGJpdHMgb25seQogICAgICAgIG15ICR0eXBlID0g JHJ7J3JfaW5mbyd9ICYgMHgwZjsgCiAgICAgICAgbXkgJHN5bV9uYW1lID0gJHN5bXRhYlskc3lt X25keF17J25hbWUnfTsKICAgICAgICBteSAkc3ltX3NobmR4ID0gJHN5bXRhYlskc3ltX25keF17 J3N0X3NobmR4J307CgogICAgICAgICRyeyd0eXBlJ30gPSAkdHlwZTsKICAgICAgICAkcnsnc3lt bmR4J30gPSAkc3ltX25keDsKICAgICAgICBwdXNoIEByZWxvY3MsIFwlcjsKCiAgICAgICAgIyBz YXZlIGV4dGVybmFsIHN5bWJvbHMgKHN0X3NobmR4IG9mIHR5cGUgJ1VORCcpCiAgICAgICAgIyB0 aGUgbnVtX2V4dHN5bSBjb3VudGVyIGlzIHVzZWQgbGF0ZXIgZm9yIGxvb2t1cCBpbiBhICdqdW1w IHRhYmxlJwogICAgICAgICRleHRzeW17JHN5bV9uYW1lfSA9ICRudW1fZXh0c3ltKysgaWYoJHN5 bV9zaG5keCA9PSAwKTsKICAgIH0KICAgIHNlZWsgJGVmaCwgJGN1cnJfZmlsZV9vZmZzZXQsICJT RUVLX1NFVCI7Cn0KCiMgZ2x1ZSBpdCBhbGwgdG9nZXRoZXIKc3ViIHBhcnNlX2VsZiB7CiAgICBt eSAkZmggPSBzaGlmdDsKICAgICRlZmggPSAkZmg7CiAgICAKICAgIHBhcnNlX2VoZHIoKTsKICAg IHBhcnNlX3NodGFiKCk7CiAgICBwYXJzZV9zZWNuYW1lcygpOwogICAgcGFyc2Vfc3ltdGFiKCk7 CiAgICBwYXJzZV9yZWxvY3MoKTsKfQoKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyBwZWVrICYg cG9rZSAKIwojIG9yaWdpbmFsIGNvZGUgYnkgTmljayBMYW5kZXJzCiMgaHR0cHM6Ly9naXN0Lmdp dGh1Yi5jb20vbW9ub3hnYXMvYzBiMGYwODZmYzdhYTA1N2E4MjU2YjQyYzY2NzYxYzgKIwojIGFk YXB0ZWQgZm9yIExpbnV4IHg2NCBieSBpc3JhCiMgbW9zdCBvZiB0aGUgY29tbWVudHMgYXJlIGZy b20gdGhlIG9yaWdpbmFsIGF1dGhvcgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgojIHBhY2sgdmFs dWUgaW50byBhbiB1bnNpZ25lZCBxdWFsIHZhbHVlIChmb3IgbWVtb3J5IGFkZHJlc3NlcykKc3Vi IF9wYWNrX2FkZHJlc3MgewogICAgbXkgJHAgPSBwYWNrKCJRIiwgJF9bMF0pOwogICAgcmV0dXJu ICRwOwp9CgojIGNvbnZlcnQgdmFsdWUgaW50byBhIFN2UFYKc3ViIHBlZWsgewogICAgdW5wYWNr ICJQJF9bMV0iLCBfcGFja19hZGRyZXNzKCRfWzBdKTsKfQoKIyBjb3B5ICRieXRlcyBvZiBsZW5n dGggJGxlbiBpbnRvIGFkZHJlc3MgJGxvY2F0aW9uCnN1YiBwb2tlIHsKICAgIG15KCRsb2NhdGlv biwgJGJ5dGVzLCAkbGVuKSA9IEBfOwogICAgbXkgJGFkZHIgPSBfcGFja19hZGRyZXNzKCRsb2Nh dGlvbik7CiAgICAjIGNvbnN0cnVjdCBhIEI6OlBWIG9iamVjdCwgYmFja2VkIGJ5IGEgU1YvU3ZQ ViB0byBhIGR1bW15IHN0cmluZyAKICAgICMgbGVuZ3RoKCRieXRlcykgbG9uZywgYW5kIHN1YnN0 aXR1dGUgJGxvY2F0aW9uIGFzIHRoZSBhY3R1YWwgc3RyaW5nCiAgICAjIHN0b3JhZ2Ugd2Ugc3Bl Y2lmaWNhbGx5IHVzZSB0aGUgc2FtZSBsZW5ndGggc28gd2UgZG8gbm90IGhhdmUgdG8KICAgICMg ZGVhbCB3aXRoIHJlc2l6aW5nCiAgICBteSAkZHVtbXkgPSAnWCcgeCAkbGVuOwogICAgbXkgJGR1 bW15X2FkZHIgPSBcJGR1bW15ICsgMDsKICAgIG15ICRnaG9zdF9zdl9jb250ZW50cyA9IHBlZWso JGR1bW15X2FkZHIsIDggKyA0ICsgNCArICRDb25maWd7aXZzaXplfSk7CgoKICAgIHN1YnN0cigg JGdob3N0X3N2X2NvbnRlbnRzLCA4ICsgNCArIDQsIDggKSA9ICRhZGRyOyAgICAKCiAgICBteSAk Z2hvc3Rfc3RyaW5nX3JlZiA9IGJsZXNzKCBcIHVucGFjaygKICAgICAgICAiUSIsCiAgICAgICAg IyBpdCdzIGNydWNpYWwgdG8gY3JlYXRlIGEgY29weSBvZiAkc3ZfY29udGVudHMsIGFuZCB3b3Jr IHdpdGggYQogICAgICAgICMgdGVtcG9yYXJ5IG1lbW9yeSBsb2NhdGlvbi4gT3RoZXJ3aXNlIHBl cmwgbWVtb3J5IGFsbG9jYXRpb24gd2lsbAogICAgICAgICMga2ljayBpbiBhbmQgd3JlYWsgY29u c2lkZXJhYmxlIGhhdm9jIGN1bG1pbmF0aW5nIHdpdGggYW4gaW5ldml0YWJsZQogICAgICAgICMg c2VnZmF1bHQKICAgICAgICBkbyB7IG5vIHdhcm5pbmdzICdwYWNrJzsgcGFjayggJ1AnLCAkZ2hv c3Rfc3ZfY29udGVudHMuJycgKSB9LAogICAgKSwgJ0I6OlBWJyApLT5vYmplY3RfMnN2cmVmOwog ICAgIyBub3cgd2hlbiB3ZSB3cml0ZSB0byB0aGUgbmV3bHkgY3JlYXRlZCAic3RyaW5nIiB3ZSBh cmUgYWN0dWFsbHkgd3JpdGluZwogICAgIyB0byAkbG9jYXRpb24uIG5vdGUgd2UgSEFWRSB0byB1 c2UgbHZhbHVlIHN1YnN0ciAtIGEgcGxhaW4gYXNzaWdubWVudCB3aWxsCiAgICAjIGFkZCBhIFww CiAgICAjCiAgICAjIEFsc28gaW4gb3JkZXIgdG8ga2VlcCB0aHJlYWRpbmcgb24gcGVybCA1Ljgu eCBoYXBweSB3ZSAqaGF2ZSogdG8gcGVyZm9ybQogICAgIyB0aGlzIGluIGEgc3RyaW5nIGV2YWwu IEkgZG9uJ3QgaGF2ZSB0aGUgc2xpZ2h0ZXN0IGlkZWEgd2h5IDopICAgIAogICAgZXZhbCAnc3Vi c3RyKCQkZ2hvc3Rfc3RyaW5nX3JlZiwgMCwgJGxlbikgPSAkYnl0ZXMnOwogICAgcmV0dXJuICRs ZW47Cn0KCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMgbWFwIGVsZiB4NjQKIwojIHJlZmVyZW5j ZXM6CiMgIC0gaHR0cHM6Ly9ibG9nLmNsb3VkZmxhcmUuY29tL2hvdy10by1leGVjdXRlLWFuLW9i amVjdC1maWxlLXBhcnQtMS8KIyAgLSBodHRwczovL2Jsb2cuY2xvdWRmbGFyZS5jb20vaG93LXRv LWV4ZWN1dGUtYW4tb2JqZWN0LWZpbGUtcGFydC0yLwojICAtIGh0dHBzOi8vYmxvZy5jbG91ZGZs YXJlLmNvbS9ob3ctdG8tZXhlY3V0ZS1hbi1vYmplY3QtZmlsZS1wYXJ0LTMvIAojIyMjIyMjIyMj IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj IyMjIyMjIyMjIyMjCgojIDRLIHBhZ2VzIApzdWIgcGFnZV9hbGlnbiB7CiAgICBteSAkbiA9IHNo aWZ0OwogICAgcmV0dXJuICgkbiArICg0MDk2IC0gMSkpICYgfig0MDk2IC0gMSk7Cn0KCiMgbWVt b3J5IG1hcApzdWIgbW1hcCB7CiAgICAjIHN5c2NhbGwgbnVtYmVyIGZvciBtbWFwIGlzIDkgb24g TGludXggeDg2XzY0CiAgICAjICRhZGRyIGNhbiBiZSBhIGZpeGVkIHZhbHVlLCBvciAwIHRvIGxl dCBtbWFwIGNob29zZSBvbmUKICAgICMgaXQgcmV0dXJucyBhIHBvaW50ZXIgdG8gdGhlIG1hcHBl ZCBhcmVhIG9uIHN1Y2Nlc3MsIC0xIG9uIGZhaWx1cmUKICAgIG15ICgkYWRkciwgJHNpemUsICRw cm90ZWN0LCAkZmxhZ3MpID0gQF87CiAgICBteSAkcmV0ID0gc3lzY2FsbCg5LCAkYWRkciwgJHNp emUsICRwcm90ZWN0LCAkZmxhZ3MsIC0xLCAwKTsKICAgIHJldHVybiAkcmV0Owp9CgojIG1lbW9y eSBwcm90ZWN0CnN1YiBtcHJvdGVjdCB7CiAgICAjIGl0IHJldHVybnMgMCBvbiBzdWNjZXNzLCAt MSBvbiBmYWlsdXJlCiAgICBteSAoJGFkZHIsICRzaXplLCAkcHJvdGVjdCkgPSBAXzsKICAgIG15 ICRyZXQgPSBzeXNjYWxsKDEwLCAkYWRkciwgJHNpemUsICRwcm90ZWN0KTsKICAgIHJldHVybiAk cmV0Owp9CgojIGNhbGN1bGF0ZSBhbmQgYXBwbHkgcmVsb2NhdGlvbnMKc3ViIGRvX3JlbG9jcyB7 CiAgICAjIHBvaW50ZXJzIHRvIG1hcHBlZCBzZWdtZW50cyBhbmQgJ2p1bXAgdGFibGUnCiAgICBt eSAkdGV4dF9wdHIgICAgPSBzaGlmdDsKICAgIG15ICRkYXRhX3B0ciAgICA9IHNoaWZ0OwogICAg bXkgJHJvZGF0YV9wdHIgID0gc2hpZnQ7CiAgICBteSAkam1wdGFiX3B0ciAgPSBzaGlmdDsKICAg IG15ICRydCAgICAgICAgICA9ICRzaHRhYlskcmVsYXRleHRfbmR4XTsKICAgIG15ICRudW1fcmVs b2NzICA9ICRydC0+eydzaF9zaXplJ30vJHJ0LT57J3NoX2VudHNpemUnfTsKIAogICAgZm9yICht eSAkaSA9IDA7ICRpIDwgJG51bV9yZWxvY3M7ICRpKyspIHsKICAgICAgICAjIHdoZXJlIHRvIHBh dGNoIC50ZXh0IAogICAgICAgIG15ICRzeW1fbmR4ID0gJHJlbG9jc1skaV17J3N5bW5keCd9Owog ICAgCiAgICAgICAgIyBzeW1ib2wgYW5kIHNlY3Rpb24gd2l0aCByZXNwZWN0IHRvIHdoaWNoIHRo ZSByZWxvY2F0aW9uIGlzIHBlcmZvcm1lZAogICAgICAgICMgZXh0ZXJuYWwgc3ltYm9scyBhcmUg aWRlbnRpZmllZCBieSBzdF9zaG5keCA9PSAwICh0eXBlIFVORCkKICAgICAgICBteSAkc3ltX25h bWUgPSAkc3ltdGFiWyRzeW1fbmR4XXsnbmFtZSd9OwogICAgICAgIG15ICRzeW1fc2huZHggPSAk c3ltdGFiWyRzeW1fbmR4XXsnc3Rfc2huZHgnfTsKICAgICAgICBteSAkc2VjX25hbWUgPSAkc2h0 YWJbJHN5bV9zaG5keF17J25hbWUnfTsKCiAgICAgICAgaWYoJHNlY19uYW1lIGVxICcudGV4dCcg fHwgJHNlY19uYW1lIGVxICcuZGF0YScgCiAgICAgICAgICAgIHx8ICRzZWNfbmFtZSBlcSAnLnJv ZGF0YScgfHwgJHN5bV9zaG5keCA9PSAwKSB7CiAgICAgICAgICAgIG15ICRiYXNlX3B0cjsKICAg ICAgICAgICAgbXkgJHBhdGNoX29mZnNldCA9ICR0ZXh0X3B0ciArICRyZWxvY3NbJGldeydyX29m ZnNldCd9OwoKICAgICAgICAgICAgJGJhc2VfcHRyID0gJHRleHRfcHRyIGlmKCRzZWNfbmFtZSBl cSAnLnRleHQnKTsKICAgICAgICAgICAgJGJhc2VfcHRyID0gJGRhdGFfcHRyIGlmKCRzZWNfbmFt ZSBlcSAnLmRhdGEnKTsKICAgICAgICAgICAgJGJhc2VfcHRyID0gJHJvZGF0YV9wdHIgaWYoJHNl Y19uYW1lIGVxICcucm9kYXRhJyk7CgogICAgICAgICAgICBteSAkc3ltX2FkZHI7CiAgICAgICAg ICAgIGlmKCRzeW1fc2huZHggIT0gMCkgewogICAgICAgICAgICAgICAgJHN5bV9hZGRyID0gJGJh c2VfcHRyICsgJHN5bXRhYlskc3ltX25keF17J3N0X3ZhbHVlJ307CiAgICAgICAgICAgIH0gZWxz ZSB7CiAgICAgICAgICAgICAgICAjIGV4dGVybmFsIHN5bWJvbHMKCiAgICAgICAgICAgICAgICAj IGEgJ2p1bXAgdGFibGUnIGlzIHVzZWQgZm9yIGp1bXBpbmcgdG8gZXh0ZXJuYWwgYWRkcmVzc2Vz CiAgICAgICAgICAgICAgICAjIGVhY2ggZW50cnkgb24gdGhlICdqdW1wIHRhYmxlJyB1c2VzIDE0 IGJ5dGVzOiA4IGJ5dGVzIGZvcgogICAgICAgICAgICAgICAgIyB0aGUgZXh0ZXJuYWwgYWRkcmVz cyB3aGVyZSB0byBqdW1wICsgNiBieXRlcyBmb3IgdGhlIGp1bXAKICAgICAgICAgICAgICAgICMg aW5zdHJ1Y3Rpb24KCiAgICAgICAgICAgICAgICAjIG9mZnNldCBvbiB0aGUgJ2p1bXAgdGFibGUn IGlzIGNhbGN1bGF0ZWQgYmFzZWQgb24gdGhlIG51bWJlcgogICAgICAgICAgICAgICAgIyBvZiBl eHRlcm5hbCBzeW1ib2xzOyBmaXJzdCBlbnRyeSBzdGFydHMgYXQgb2Zmc2V0IDAsIHNlY29uZAog ICAgICAgICAgICAgICAgIyBhdCBvZmZzZXQgMTQsIHRoaXJkIGF0IG9mZnNldCAyOCwgYW5kIHNv IG9uIGFuZCBzbyBmb3J0aAogICAgICAgICAgICAgICAgbXkgJGptcHRhYl9uZHggPSAkam1wdGFi X3B0ciArICgkZXh0c3lteyRzeW1fbmFtZX0qMTQpOwoKICAgICAgICAgICAgICAgICMgdGhlIHN5 bWJvbCBhZGRyZXNzIHVzZWQgZm9yIHRoZSByZWxvY2F0aW9uIGZvcm11bGEgc2hvdWxkCiAgICAg ICAgICAgICAgICAjIHBvaW50IHRvIHRoZSBqdW1wIGluc3RydWN0aW9uIGluIHRoZSAnanVtcCB0 YWJsZScgZW50cnksIHRodXMKICAgICAgICAgICAgICAgICMgdGhlIGZpcnN0IDggYnl0ZXMgYXJl IHNraXBwZWQKICAgICAgICAgICAgICAgICRzeW1fYWRkciA9ICRqbXB0YWJfbmR4ICsgODsKCiAg ICAgICAgICAgICAgICAjIHRoZSBhY3R1YWwgZXh0ZXJuYWwgc3ltYm9sIGFkZHJlc3MgCiAgICAg ICAgICAgICAgICBteSAkZXh0X2FkZHIgPSBEeW5hTG9hZGVyOjpkbF9maW5kX3N5bWJvbCgkbGli cmVmLCAkc3ltX25hbWUpOwoKICAgICAgICAgICAgICAgICMgcGFjayBhZGRyZXNzIGluIGxpdHRs ZSBlbmRpYW4gb3JkZXIgYW5kIHRoZW4gYXBwZW5kIHRoZSBqdW1wOgogICAgICAgICAgICAgICAg IyAweGZmIDB4MjUgZm9yIHRoZSBpbnN0cnVjdGlvbiBpdHNlbGYgYW5kIDB4ZmZmZmZmZjIgPSAt MTQgZm9yCiAgICAgICAgICAgICAgICAjIHRoZSBvZmZzZXQgKGp1bXAgMTQgYnl0ZXMgYmFja3dh cmRzIHRvIHRoZSBleHRlcm5hbCBhZGRyZXNzKQoKICAgICAgICAgICAgICAgICMgIlYiIGZvcm1h dCBpcyA0IGJ5dGVzOyBleHRlcm5hbCBhZGRyZXNzIGlzIDggYnl0ZXMKICAgICAgICAgICAgICAg IG15ICgkcDEsICRwMikgPSB1bnBhY2soIlYyIiwgcGFjaygiUSIsICRleHRfYWRkcikpOwogICAg ICAgICAgICAgICAgbXkgJGptcHRhYl9lbnRyeSA9IHBhY2soIlYiLCAkcDEpOwogICAgICAgICAg ICAgICAgJGptcHRhYl9lbnRyeSAuPSBwYWNrKCJWIiwgJHAyKTsKICAgICAgICAgICAgICAgICRq bXB0YWJfZW50cnkgLj0gIlx4ZmZceDI1XHhmMlx4ZmZceGZmXHhmZiI7CgogICAgICAgICAgICAg ICAgIyB1cGRhdGUgJ2p1bXAgdGFibGUnIGluIG1lbW9yeQogICAgICAgICAgICAgICAgcG9rZSgk am1wdGFiX25keCwgJGptcHRhYl9lbnRyeSwgbGVuZ3RoKCRqbXB0YWJfZW50cnkpKTsKICAgICAg ICAgICAgfQogICAgIAogICAgICAgICAgICAjIFJfWDg2XzY0X1BMVDMyICg0KSBhbmQgUl9YODZf NjRfUEMzMiAoMikgcmVsb2NhdGlvbnMKICAgICAgICAgICAgIyBpdCB1c2VzIHRoZSBmb3JtdWxh ZSBMICsgQSAtIFAgYW5kIFMgKyBBIC0gUCwgYXNzdW1pbmcgTCA9IFMKICAgICAgICAgICAgaWYo JHJlbG9jc1skaV17J3R5cGUnfSA9PSA0IG9yICRyZWxvY3NbJGldeyd0eXBlJ30gPT0gMikgewog ICAgICAgICAgICAgICAgbXkgJHJlbG8gPSAkc3ltX2FkZHIgKyAkcmVsb2NzWyRpXXsncl9hZGRl bmQnfSAtICRwYXRjaF9vZmZzZXQ7CiAgICAgICAgICAgICAgICAjIHBhY2sgaW4gbGl0dGxlIGVu ZGlhbiBvcmRlciAoNCBieXRlcykKICAgICAgICAgICAgICAgICRyZWxvID0gcGFjaygiViIsICRy ZWxvKTsKICAgICAgICAgICAgICAgICMgYXBwbHkgcmVsb2NhdGlvbiBieSBzaW1wbHkgY29weWlu ZyB0aGUgY2FsY3VsYXRlZCBhZGRyZXNzCiAgICAgICAgICAgICAgICAjIGludG8gdGhlIHBhdGNo IG9mZnNldCBhZGRyZXNzCiAgICAgICAgICAgICAgICBwb2tlKCRwYXRjaF9vZmZzZXQsICRyZWxv LCBsZW5ndGgoJHJlbG8pKTsKICAgICAgICAgICAgfQogICAgICAgIH0gCiAgICB9Cn0KCiMgbWFw IGNvZGUgKG1lbW9yeSBtYXAsIHBva2UgY29kZSwgcmVsb2NhdGUsIG1lbW9yeSBwcm90ZWN0KQpz dWIgbWFwX2VsZiB7CiAgICBteSAkY29kZSA9IHNoaWZ0OwoKICAgIG15ICRiYXNlX3B0ciA9IG1t YXAoMCwgbGVuZ3RoKCRjb2RlKSwgMywgMzMpOwogICAgaWYoJGJhc2VfcHRyID09IC0xKSB7CiAg ICAgICAgcHJpbnQgIkZhaWxlZCB0byBhbGxvY2F0ZSBtZW1vcnkgZm9yIEVMRlxuIjsKICAgICAg ICBleGl0OwogICAgfQoKICAgIHBva2UoJGJhc2VfcHRyLCAkY29kZSwgbGVuZ3RoKCRjb2RlKSk7 CgogICAgbXkgJHRleHQgICAgPSAkc2h0YWJbJHRleHRfbmR4XTsKICAgIG15ICRkYXRhICAgID0g JHNodGFiWyRkYXRhX25keF07CiAgICBteSAkcm9kYXRhICA9ICRzaHRhYlskcm9kYXRhX25keF07 CgogICAgIyBzaXplIG9mICdqdW1wIHRhYmxlJyBpcyBudW1iZXIgb2YgZXh0ZXJuYWwgc3ltYm9s cyAqIDE0IGJ5dGVzCiAgICBteSAkam1wdGFiX3NpemUgPSAkbnVtX2V4dHN5bSoxNDsKCiAgICAj IG1hcCBzZWdtZW50cyBhbmQgJ2p1bXAgdGFibGUnIG5leHQgdG8gZWFjaCBvdGhlcgogICAgbXkg JHRleHRfcHRyID0gbW1hcCgKICAgICAgICAwLCAKICAgICAgICBwYWdlX2FsaWduKCR0ZXh0LT57 J3NoX3NpemUnfSkgKyAKICAgICAgICBwYWdlX2FsaWduKCRkYXRhLT57J3NoX3NpemUnfSkgKyAK ICAgICAgICBwYWdlX2FsaWduKCRyb2RhdGEtPnsnc2hfc2l6ZSd9KSArCiAgICAgICAgcGFnZV9h bGlnbigkam1wdGFiX3NpemUpLCAKICAgICAgICAzLCAKICAgICAgICAzMwogICAgKTsKICAgIGlm ICgkdGV4dF9wdHIgPT0gLTEpIHsKICAgICAgICBwcmludCAiRmFpbGVkIHRvIGFsbG9jYXRlIG1l bW9yeSBmb3IgLnRleHRcbiI7CiAgICAgICAgZXhpdDsKICAgIH0KICAgIAogICAgbXkgJGRhdGFf cHRyICAgPSAkdGV4dF9wdHIgKyBwYWdlX2FsaWduKCR0ZXh0LT57J3NoX3NpemUnfSk7CiAgICBt eSAkcm9kYXRhX3B0ciA9ICRkYXRhX3B0ciArIHBhZ2VfYWxpZ24oJGRhdGEtPnsnc2hfc2l6ZSd9 KTsKICAgIG15ICRqbXB0YWJfcHRyID0gJHJvZGF0YV9wdHIgKyBwYWdlX2FsaWduKCRyb2RhdGEt Pnsnc2hfc2l6ZSd9KTsKCiAgICAjIGNvcHkgc2VnbWVudHMgaW50byBtZW1vcnkKICAgIHBva2Uo CiAgICAgICAgJHRleHRfcHRyLCAKICAgICAgICBzdWJzdHIoJGNvZGUsICR0ZXh0LT57J3NoX29m ZnNldCd9LCAkdGV4dC0+eydzaF9zaXplJ30pCiAgICApOwoKICAgIHBva2UoCiAgICAgICAgJGRh dGFfcHRyLCAKICAgICAgICBzdWJzdHIoJGNvZGUsICRkYXRhLT57J3NoX29mZnNldCd9LCAkZGF0 YS0+eydzaF9zaXplJ30pCiAgICApOwoKICAgIHBva2UoCiAgICAgICAgJHJvZGF0YV9wdHIsIAog ICAgICAgIHN1YnN0cigkY29kZSwgJHJvZGF0YS0+eydzaF9vZmZzZXQnfSwgJHJvZGF0YS0+eydz aF9zaXplJ30pCiAgICApOwoKICAgIGRvX3JlbG9jcygkdGV4dF9wdHIsICRkYXRhX3B0ciwgJHJv ZGF0YV9wdHIsICRqbXB0YWJfcHRyKTsKCiAgICBpZihtcHJvdGVjdCgkdGV4dF9wdHIsICR0ZXh0 LT57J3NoX3NpemUnfSwgNSkgPT0gLTEpIHsKICAgICAgICBwcmludCAiRmFpbGVkIHRvIG1wcm90 ZWN0IC50ZXh0XG4iOwogICAgICAgIGV4aXQ7CiAgICB9CgogICAgIyBjaGVjayAucm9kYXRhIHNo X3NpemUgZmlyc3QgaW4gY2FzZSBpcyBub3QgZGVmaW5lZAogICAgaWYoZXhpc3RzICRyb2RhdGEt Pnsnc2hfc2l6ZSd9KSB7CiAgICAgICAgaWYobXByb3RlY3QoJHJvZGF0YV9wdHIsICRyb2RhdGEt Pnsnc2hfc2l6ZSd9LCAxKSA9PSAtMSkgewogICAgICAgICAgICBwcmludCAiRmFpbGVkIHRvIG1w cm90ZWN0IC5yb2RhdGFcbiI7CiAgICAgICAgICAgIGV4aXQ7CiAgICAgICAgfQogICAgfQoKICAg IGlmKG1wcm90ZWN0KCRqbXB0YWJfcHRyLCAkam1wdGFiX3NpemUsIDUpID09IC0xKSB7CiAgICAg ICAgcHJpbnQgIkZhaWxlZCB0byBtcHJvdGVjdCBqdW1wIHRhYmxlXG4iOwogICAgICAgIGV4aXQ7 CiAgICB9CgogICAgIyByZXR1cm4gcG9pbnRlciB0byBzdGFydCBvZiB0aGUgdGV4dCBzZWdtZW50 CiAgICAjIGl0IHdpbGwgYmUgdXNlZCB0byBjYWxjdWxhdGUgdGhlIHBvaW50ZXIgb2YgdGhlIGZ1 bmN0aW9uIHRvIGJlIGV4ZWN1dGVkCiAgICByZXR1cm4gJHRleHRfcHRyOwp9CgojIGV4ZWN1dGUg bWFwcGVkIGZ1bmN0aW9uIChlLmcuIG1haW4pCnN1YiBleGVjX2Z1bmMgewogICAgbXkgJGZ1bmNf bmFtZSAgID0gc2hpZnQ7CiAgICBteSAkdGV4dF9wdHIgICAgPSBzaGlmdDsKICAgIG15ICRmdW5j X3B0ciAgICA9ICRmdW5jc3skZnVuY19uYW1lfTsKCiAgICBteSAkZnVuYyA9IER5bmFMb2FkZXI6 OmRsX2luc3RhbGxfeHN1YigKICAgICAgICAiX2phcGgiLCAjIG5vdCByZWFsbHkgdXNlZAogICAg ICAgICR0ZXh0X3B0ciArICRmdW5jX3B0ciwgCiAgICAgICAgX19GSUxFX18gIyBubyBmaWxlCiAg ICApOwoKICAgICMgZGVyZWZlcmVuY2UgYW5kIGV4ZWN1dGUKICAgICZ7JGZ1bmN9Owp9CgoKIyMj IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj IyMjIyMjIyMjIyMjIyMjIyMjIwojIG1haW4KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKbXkgKCRj b2RlLCAkZmgpID0gcmVhZF9lbGYoKTsKcGFyc2VfZWxmKCRmaCk7Cm15ICR0ZXh0X3B0ciA9IG1h cF9lbGYoJGNvZGUpOwpleGVjX2Z1bmMoJ21haW4nLCAkdGV4dF9wdHIpOwoKCiMjIyMjIyMjIyMj IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj IyMjIyMjIyMjIyMKIyBFTEYgYmluYXJ5IGNvbnRlbnQKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoK IyBoYXJkY29kZWQgdG8gYWNoaWV2ZSBmZC1sZXNzIGV4ZWN1dGlvbgojIHBlcmwgLWUgJ3ByaW50 Im15IFwkY29kZSA9IFwiXCI7XG4iOyQvPVwzMjsnIFwKIyAtZSAncHJpbnQiXCRjb2RlIC49IHBh Y2sgcS9IKi8sIHEvIi4odW5wYWNrIkgqIikuIi87XG4iIHdoaWxlKDw+KScgLi9vYmoubwojCiMg aGFyZGNvZGVkIEMgY29kZToKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBCRUdJTiBvYmouYyAt LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KIyAjaW5jbHVkZSA8c3RkaW8u aD4KIyAKIyB2b2lkIHByaW50X2phcGgodm9pZCkgewojICAgICBwdXRjaGFyKCdqJyk7CiMgICAg IHB1dGNoYXIoJ2EnKTsKIyAgICAgcHV0Y2hhcigncCcpOwojICAgICBwdXRjaGFyKCdoJyk7CiMg ICAgIHB1dGNoYXIoJ1xuJyk7CiMgfQojIAojIGludCBtYWluKHZvaWQpIHsKIyAgICAgY2hhciAq c3RyID0gImkgYW0gYW4gZWxmIjsKIyAKIyAgICAgcHJpbnRmKCIlc1xuIiwgc3RyKTsKIyAgICAg cHJpbnRfamFwaCgpOwojIAojICAgICByZXR1cm4gMDsKIyB9CiMgLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0gRU5EIG9iai5jIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t CiMKCnN1YiBnZXRfY29kZSB7CiAgICBteSAkY29kZSA9ICIiOwogICAgJGNvZGUgLj0gcGFjayBx L0gqLywgcS83ZjQ1NGM0NjAyMDEwMTAwMDAwMDAwMDAwMDAwMDAwMDAxMDAzZTAwMDEwMDAwMDAw MDAwMDAwMDAwMDAwMDAwLzsKICAgICRjb2RlIC49IHBhY2sgcS9IKi8sIHEvMDAwMDAwMDAwMDAw MDAwMDE4MDQwMDAwMDAwMDAwMDAwMDAwMDAwMDQwMDAwMDAwMDAwMDQwMDAwZDAwMGMwMC87CiAg ICAkY29kZSAuPSBwYWNrIHEvSCovLCBxLzU1NDg4OWU1YmY2YTAwMDAwMGU4MDAwMDAwMDBiZjYx MDAwMDAwZTgwMDAwMDAwMGJmNzAwMDAwMDBlODAwMDAvOwogICAgJGNvZGUgLj0gcGFjayBxL0gq LywgcS8wMDAwYmY2ODAwMDAwMGU4MDAwMDAwMDBiZjBhMDAwMDAwZTgwMDAwMDAwMDkwNWRjMzU1 NDg4OWU1NDg4M2VjLzsKICAgICRjb2RlIC49IHBhY2sgcS9IKi8sIHEvMTA0ODhkMDUwMDAwMDAw MDQ4ODk0NWY4NDg4YjQ1Zjg0ODg5YzdlODAwMDAwMDAwZTgwMDAwMDAwMGI4MDAwMC87CiAgICAk Y29kZSAuPSBwYWNrIHEvSCovLCBxLzAwMDBjOWMzNjkyMDYxNmQyMDYxNmUyMDY1NmM2NjAwMDA0 NzQzNDMzYTIwMjg0NDY1NjI2OTYxNmUyMDMxMzAvOwogICAgJGNvZGUgLj0gcGFjayBxL0gqLywg cS8yZTMyMmUzMTJkMzYyOTIwMzEzMDJlMzIyZTMxMjAzMjMwMzIzMTMwMzEzMTMwMDAxNDAwMDAw MDAwMDAwMDAwLzsKICAgICRjb2RlIC49IHBhY2sgcS9IKi8sIHEvMDE3YTUyMDAwMTc4MTAwMTFi MGMwNzA4OTAwMTAwMDAxYzAwMDAwMDFjMDAwMDAwMDAwMDAwMDAzOTAwMDAwMC87CiAgICAkY29k ZSAuPSBwYWNrIHEvSCovLCBxLzAwNDEwZTEwODYwMjQzMGQwNjc0MGMwNzA4MDAwMDAwMWMwMDAw MDAzYzAwMDAwMDAwMDAwMDAwMmIwMDAwMDAvOwogICAgJGNvZGUgLj0gcGFjayBxL0gqLywgcS8w MDQxMGUxMDg2MDI0MzBkMDY2NjBjMDcwODAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw MDAwMDAwLzsKICAgICRjb2RlIC49IHBhY2sgcS9IKi8sIHEvMDAwMDAwMDAwMDAwMDAwMDAxMDAw MDAwMDQwMGYxZmYwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMC87CiAgICAkY29kZSAu PSBwYWNrIHEvSCovLCBxLzAwMDAwMDAwMDMwMDAxMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw MDAwMDAwMDAwMDAwMDAwMDMwMDAzMDAvOwogICAgJGNvZGUgLj0gcGFjayBxL0gqLywgcS8wMDAw MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDMwMDA0MDAwMDAwMDAwMDAwMDAw MDAwLzsKICAgICRjb2RlIC49IHBhY2sgcS9IKi8sIHEvMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw MDMwMDA1MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMC87CiAgICAkY29kZSAuPSBw YWNrIHEvSCovLCBxLzAwMDAwMDAwMDMwMDA3MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw MDAwMDAwMDAwMDAwMDMwMDA4MDAvOwogICAgJGNvZGUgLj0gcGFjayBxL0gqLywgcS8wMDAwMDAw MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDMwMDA2MDAwMDAwMDAwMDAwMDAwMDAw LzsKICAgICRjb2RlIC49IHBhY2sgcS9IKi8sIHEvMDAwMDAwMDAwMDAwMDAwMDA3MDAwMDAwMTIw MDAxMDAwMDAwMDAwMDAwMDAwMDAwMzkwMDAwMDAwMDAwMDAwMC87CiAgICAkY29kZSAuPSBwYWNr IHEvSCovLCBxLzEyMDAwMDAwMTAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw MDI4MDAwMDAwMTAwMDAwMDAvOwogICAgJGNvZGUgLj0gcGFjayBxL0gqLywgcS8wMDAwMDAwMDAw MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDMwMDAwMDAwMTIwMDAxMDAzOTAwMDAwMDAwMDAwMDAwLzsK ICAgICRjb2RlIC49IHBhY2sgcS9IKi8sIHEvMmIwMDAwMDAwMDAwMDAwMDM1MDAwMDAwMTAwMDAw MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMC87CiAgICAkY29kZSAuPSBwYWNrIHEv SCovLCBxLzAwNmY2MjZhMmU2MzAwNzA3MjY5NmU3NDVmNmE2MTcwNjgwMDVmNDc0YzRmNDI0MTRj NWY0ZjQ2NDY1MzQ1NTQvOwogICAgJGNvZGUgLj0gcGFjayBxL0gqLywgcS81ZjU0NDE0MjRjNDU1 ZjAwNzA3NTc0NjM2ODYxNzIwMDZkNjE2OTZlMDA3MDc1NzQ3MzAwMDAwMDAwMDAwMDAwLzsKICAg ICRjb2RlIC49IHBhY2sgcS9IKi8sIHEvMGEwMDAwMDAwMDAwMDAwMDA0MDAwMDAwMGIwMDAwMDBm Y2ZmZmZmZmZmZmZmZmZmMTQwMDAwMDAwMDAwMDAwMC87CiAgICAkY29kZSAuPSBwYWNrIHEvSCov LCBxLzA0MDAwMDAwMGIwMDAwMDBmY2ZmZmZmZmZmZmZmZmZmMWUwMDAwMDAwMDAwMDAwMDA0MDAw MDAwMGIwMDAwMDAvOwogICAgJGNvZGUgLj0gcGFjayBxL0gqLywgcS9mY2ZmZmZmZmZmZmZmZmZm MjgwMDAwMDAwMDAwMDAwMDA0MDAwMDAwMGIwMDAwMDBmY2ZmZmZmZmZmZmZmZmZmLzsKICAgICRj b2RlIC49IHBhY2sgcS9IKi8sIHEvMzIwMDAwMDAwMDAwMDAwMDA0MDAwMDAwMGIwMDAwMDBmY2Zm ZmZmZmZmZmZmZmZmNDQwMDAwMDAwMDAwMDAwMC87CiAgICAkY29kZSAuPSBwYWNrIHEvSCovLCBx LzAyMDAwMDAwMDUwMDAwMDBmY2ZmZmZmZmZmZmZmZmZmNTQwMDAwMDAwMDAwMDAwMDA0MDAwMDAw MGQwMDAwMDAvOwogICAgJGNvZGUgLj0gcGFjayBxL0gqLywgcS9mY2ZmZmZmZmZmZmZmZmZmNTkw MDAwMDAwMDAwMDAwMDA0MDAwMDAwMDkwMDAwMDBmY2ZmZmZmZmZmZmZmZmZmLzsKICAgICRjb2Rl IC49IHBhY2sgcS9IKi8sIHEvMjAwMDAwMDAwMDAwMDAwMDAyMDAwMDAwMDIwMDAwMDAwMDAwMDAw MDAwMDAwMDAwNDAwMDAwMDAwMDAwMDAwMC87CiAgICAkY29kZSAuPSBwYWNrIHEvSCovLCBxLzAy MDAwMDAwMDIwMDAwMDAzOTAwMDAwMDAwMDAwMDAwMDAyZTczNzk2ZDc0NjE2MjAwMmU3Mzc0NzI3 NDYxNjIvOwogICAgJGNvZGUgLj0gcGFjayBxL0gqLywgcS8wMDJlNzM2ODczNzQ3Mjc0NjE2MjAw MmU3MjY1NmM2MTJlNzQ2NTc4NzQwMDJlNjQ2MTc0NjEwMDJlNjI3MzczLzsKICAgICRjb2RlIC49 IHBhY2sgcS9IKi8sIHEvMDAyZTcyNmY2NDYxNzQ2MTAwMmU2MzZmNmQ2ZDY1NmU3NDAwMmU2ZTZm NzQ2NTJlNDc0ZTU1MmQ3Mzc0NjE2My87CiAgICAkY29kZSAuPSBwYWNrIHEvSCovLCBxLzZiMDAy ZTcyNjU2YzYxMmU2NTY4NWY2NjcyNjE2ZDY1MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw MDAvOwogICAgJGNvZGUgLj0gcGFjayBxL0gqLywgcS8wMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwLzsKICAgICRjb2RlIC49IHBh Y2sgcS9IKi8sIHEvMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw MDAwMjAwMDAwMDAwMTAwMDAwMC87CiAgICAkY29kZSAuPSBwYWNrIHEvSCovLCBxLzA2MDAwMDAw MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwNDAwMDAwMDAwMDAwMDAwMDY0MDAwMDAwMDAwMDAwMDAv OwogICAgJGNvZGUgLj0gcGFjayBxL0gqLywgcS8wMDAwMDAwMDAwMDAwMDAwMDEwMDAwMDAwMDAw MDAwMDAwMDAwMDAwMDAwMDAwMDAxYjAwMDAwMDA0MDAwMDAwLzsKICAgICRjb2RlIC49IHBhY2sg cS9IKi8sIHEvNDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDBjMDAyMDAwMDAwMDAwMDAw YzAwMDAwMDAwMDAwMDAwMC87CiAgICAkY29kZSAuPSBwYWNrIHEvSCovLCBxLzBhMDAwMDAwMDEw MDAwMDAwODAwMDAwMDAwMDAwMDAwMTgwMDAwMDAwMDAwMDAwMDI2MDAwMDAwMDEwMDAwMDAvOwog ICAgJGNvZGUgLj0gcGFjayBxL0gqLywgcS8wMzAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw MGE0MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwLzsKICAgICRjb2RlIC49IHBhY2sgcS9I Ki8sIHEvMDAwMDAwMDAwMDAwMDAwMDAxMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMmMw MDAwMDAwODAwMDAwMC87CiAgICAkY29kZSAuPSBwYWNrIHEvSCovLCBxLzAzMDAwMDAwMDAwMDAw MDAwMDAwMDAwMDAwMDAwMDAwYTQwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAvOwogICAg JGNvZGUgLj0gcGFjayBxL0gqLywgcS8wMDAwMDAwMDAwMDAwMDAwMDEwMDAwMDAwMDAwMDAwMDAw MDAwMDAwMDAwMDAwMDAzMTAwMDAwMDAxMDAwMDAwLzsKICAgICRjb2RlIC49IHBhY2sgcS9IKi8s IHEvMDIwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDBhNDAwMDAwMDAwMDAwMDAwMGMwMDAw MDAwMDAwMDAwMC87CiAgICAkY29kZSAuPSBwYWNrIHEvSCovLCBxLzAwMDAwMDAwMDAwMDAwMDAw MTAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDM5MDAwMDAwMDEwMDAwMDAvOwogICAgJGNv ZGUgLj0gcGFjayBxL0gqLywgcS8zMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMGIwMDAw MDAwMDAwMDAwMDAyODAwMDAwMDAwMDAwMDAwLzsKICAgICRjb2RlIC49IHBhY2sgcS9IKi8sIHEv MDAwMDAwMDAwMDAwMDAwMDAxMDAwMDAwMDAwMDAwMDAwMTAwMDAwMDAwMDAwMDAwNDIwMDAwMDAw MTAwMDAwMC87CiAgICAkY29kZSAuPSBwYWNrIHEvSCovLCBxLzAwMDAwMDAwMDAwMDAwMDAwMDAw MDAwMDAwMDAwMDAwZDgwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAvOwogICAgJGNvZGUg Lj0gcGFjayBxL0gqLywgcS8wMDAwMDAwMDAwMDAwMDAwMDEwMDAwMDAwMDAwMDAwMDAwMDAwMDAw MDAwMDAwMDA1NzAwMDAwMDAxMDAwMDAwLzsKICAgICRjb2RlIC49IHBhY2sgcS9IKi8sIHEvMDIw MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDBkODAwMDAwMDAwMDAwMDAwNTgwMDAwMDAwMDAw MDAwMC87CiAgICAkY29kZSAuPSBwYWNrIHEvSCovLCBxLzAwMDAwMDAwMDAwMDAwMDAwODAwMDAw MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDUyMDAwMDAwMDQwMDAwMDAvOwogICAgJGNvZGUgLj0g cGFjayBxL0gqLywgcS80MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDgwMDMwMDAwMDAw MDAwMDAzMDAwMDAwMDAwMDAwMDAwLzsKICAgICRjb2RlIC49IHBhY2sgcS9IKi8sIHEvMGEwMDAw MDAwODAwMDAwMDA4MDAwMDAwMDAwMDAwMDAxODAwMDAwMDAwMDAwMDAwMDEwMDAwMDAwMjAwMDAw MC87CiAgICAkY29kZSAuPSBwYWNrIHEvSCovLCBxLzAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw MDAwMDAwMzAwMTAwMDAwMDAwMDAwMDUwMDEwMDAwMDAwMDAwMDAvOwogICAgJGNvZGUgLj0gcGFj ayBxL0gqLywgcS8wYjAwMDAwMDA5MDAwMDAwMDgwMDAwMDAwMDAwMDAwMDE4MDAwMDAwMDAwMDAw MDAwOTAwMDAwMDAzMDAwMDAwLzsKICAgICRjb2RlIC49IHBhY2sgcS9IKi8sIHEvMDAwMDAwMDAw MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDA4MDAyMDAwMDAwMDAwMDAwM2EwMDAwMDAwMDAwMDAwMC87 CiAgICAkY29kZSAuPSBwYWNrIHEvSCovLCBxLzAwMDAwMDAwMDAwMDAwMDAwMTAwMDAwMDAwMDAw MDAwMDAwMDAwMDAwMDAwMDAwMDExMDAwMDAwMDMwMDAwMDAvOwogICAgJGNvZGUgLj0gcGFjayBx L0gqLywgcS8wMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMGIwMDMwMDAwMDAwMDAwMDA2 MTAwMDAwMDAwMDAwMDAwLzsKICAgICRjb2RlIC49IHBhY2sgcS9IKi8sIHEvMDAwMDAwMDAwMDAw MDAwMDAxMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwLzsKCiAgICByZXR1cm4gJGNvZGU7 Cn0=