Instruction By Instruction

Instruction By Instruction

Original post by 0xf00s, from the 0x00sec forum.

Hello, we meet again. Snagged a convo between c0z and pico the other day on real time encryption or Runtime Code Encryption, sometimes called IBI (Instruction-By-Instruction) though that name crawled out of the academic side (bunch of losers) Wanted to drop a reply in the back thread but it turned into a long ass wall of text, so I figured fuck it let's write it up proper maybe someone learns something.

So what we implement here is a "page-granular demand decryption" code pages live encrypted on disk and in memory, and are decrypted exactly one page at a time only when the CPU is about to execute them. After execution leaves the page, it is re-encrypted. At any given moment, at most one code page exists in plaintext in the process address space. This is the invariant the design must maintain, and everything else follows from it.

Back in the day, cats were already poking at this. Earliest published work on runtime ELF encryption with anti-debug? Shiva scut and grugq, circa 2001. Shiva wraps an ELF binary, encrypts the payload, blasts it out decrypted at load time into an anonymous mapping, then exec's it basically what you'd just call a loader today. The whole plaintext image is sitting naked in memory the second the constructor returns. Snapshot the process any time after startup and you've got the full code. Hard problem back then.

Also there was burneye (team teso) same fundamental idea but tightened up passphrase-derived keys, ptrace detection, TPM support in later versions. Dressed it up nice, but the bone structure was the same load-time bulk decryption. Pop it at the right moment and it's all there.

Anyway not dropping this to flex scene history. Point is to actually understand the technique, and to do that right you gotta see what problem it's trying to solve on Linux in the first place:

(a) the demand-decryption loop driven by SIGSEGV,
(b) the re-encryption loop driven by the x86 Trap Flag,
(c) with a stream cipher that supports random-access seeks,
(d) with the key isolated on a separately protected page,
(e) and all of it fitting in under few lines of code.

That is what this piece does.

— A

Consider a function ec_key that you want to protect. Without any protection, the linker places it in the .text section at some address, and it sits there as plaintext for the entire lifetime of the process. Anyone who can attach a debugger, take a core dump, or read /proc/$pid/mem gets it for free.

The idea is to place ec_key (and any other functions you want protected) in a separate ELF section we call it .foo that is:

1. Encrypted at rest in the binary on disk.
2. Mapped PROT_NONE at startup, so any access faults immediately.
3. Decrypted one page at a time, on demand, only when the CPU is
   about to execute that page.
4. Re-encrypted as soon as the CPU's instruction pointer leaves that
   page.

The first observation is that step (3) and (4) give us the invariant at most one page is ever plaintext. A process snapshot captures at most one page of code, which may not even contain the function you care about.

second observation is that steps (3) and (4) are driven entirely by the hardware's memory protection mechanism and signal delivery. We do not patch the code, insert trampolines, or modify the calling the protected functions are called exactly like normal functions the first memory access just happens to fault into our handler.

Third observation is that the encryption has to be keyed at runtime, not at build time. A build-time key is extractable from the binary by static analysis. A key generated at startup is not in the binary at all.

Demand-Decryption Engine ?

Let me explain! at startup, the constructor does:

    mprotect(foo_base, foo_size, PROT_READ | PROT_WRITE);
    for each page in .foo:
        chacha20_xor(page);          /* encrypt in place */
    mprotect(foo_base, foo_size, PROT_NONE);

After this, .foo is opaque. Calling any function in .foo immediately generates a SIGSEGV the CPU tries to fetch the instruction at the function's entry point, the MMU sees PROT_NONE, and delivers SIGSEGV with si_addr pointing to the faulting address.

Our SIGSEGV handler does:

1. Extract fault_addr from siginfo->si_addr.
2. Page-align it: fault_page = fault_addr & ~0xFFF.
3. Verify fault_page is within .foo. If not, re-raise SIGSEGV
   with the default handler (real crash).
4. If a different page is currently decrypted (g_hot != 0 and
   g_hot != fault_page), re-encrypt it first.
5. mprotect(fault_page, PROT_READ | PROT_WRITE).
6. Decrypt the page: chacha20_xor(fault_page).
7. mprotect(fault_page, PROT_READ | PROT_EXEC).
8. Set g_hot = fault_page.
9. Set the x86 Trap Flag in the saved ucontext (EFLAGS bit 8).
10. Return from the signal handler.

Returning from the signal handler resumes execution at the faulting instruction which now has PROT_READ|PROT_EXEC and is decrypted. The function runs normally.

Step (9) is the setup for re-encryption, w'll talk more in the next section.

One the signal handler itself must not fault. We allocate a separate signal stack (sigaltstack) on a locked anonymous page. If the signal handler used the normal thread stack and the thread stack itself faulted, we would get a recursive fault and deadlock. The altstack
ensures the handler always has a valid stack regardless of the state of the protected region.

Another the altstack page is mlock()'d. Without mlock, the kernel might page it out, and the page-in on first signal delivery could theoretically cause a nested fault. This is paranoid but aight.

    static void _segv(int sig, siginfo_t *info, void *uctx)
    {
        uintptr_t fault = PGN((uintptr_t)info->si_addr);
        uintptr_t base  = PGN((uintptr_t)foo_start);
        uintptr_t top   = PGN((uintptr_t)(foo_end - 1)) + PGS;

        if (fault < base || fault >= top) {
            struct sigaction sa = { .sa_handler = SIG_DFL };
            sigaction(SIGSEGV, &sa, NULL);
            raise(SIGSEGV);
            return;
        }
        if (g_hot && g_hot != fault) {
            mprotect((void *)g_hot, PGS, PROT_READ | PROT_WRITE);
            _crypt_pg(g_hot);
            mprotect((void *)g_hot, PGS, PROT_NONE);
        }
        mprotect((void *)fault, PGS, PROT_READ | PROT_WRITE);
        _crypt_pg(fault);
        mprotect((void *)fault, PGS, PROT_READ | PROT_EXEC);
        g_hot = fault;

        ucontext_t *uc = uctx;
        uc->uc_mcontext.gregs[REG_EFL] |= 0x100;  /* set TF */
    }

— B

The cipher choice matters more than it might appear. We need:

(a) A cipher that can be applied to arbitrary page offsets without
    decrypting everything before them. If we used a CBC-mode block
    cipher, decrypting page 5 would require decrypting pages 0-4
    first. That kills the "one page at a time" property.

(b) A cipher that is an involution on XOR i.e., applying it twice
    gives back the original. This is why we can use the same
    _crypt_pg function for both encryption and decryption.

(c) Speed. mprotect is not free. We are calling it three times per
    page fault. We do not want the cipher to be the bottleneck.

ChaCha20 satisfies all three. It is a stream cipher based on the Salsa20 core. The keystream is generated in 64-byte blocks, each block independently indexed by a 32-bit counter. "Random access" into the stream is therefore O(1): to decrypt bytes starting at offset N, set the block counter to N/64 and skip N%64 bytes into that block.

We expose this as :

    void cc20_seek(cc20_ctx *c, uint64_t byte_off) {
        uint32_t blk = (uint32_t)(byte_off / 64);
        int rem      = (int)(byte_off % 64);
        c->s[12] = blk;
        if (rem) {
            uint32_t tmp[16];
            _block(tmp, c->s);
            memcpy(c->buf, tmp, 64);
            c->pos = rem;
            c->s[12]++;
        } else {
            c->pos = 64;
        }
    }

To decrypt page at address P where the section starts at base B, the byte offset is simply (P - B). Pages are 4096 bytes; 4096 is a multiple of 64 (the ChaCha20 block size), so each page starts at a clean block boundary. This means cc20_seek for any page is always called with rem == 0, and we just set the counter to (P-B)/64.

    cc20_init(&c, gk->key, gk->nonce, 0);
    cc20_seek(&c, pg - PGN((uintptr_t)foo_start));
    cc20_xor(&c, (uint8_t *)pg, (const uint8_t *)pg, PGS);

Note that cc20_xor reads from and writes to the same buffer (in-place). This works because XOR is its own inverse: E(E(P)) = P. Calling first one on an encrypted page decrypts it. Calling it on a decrypted page re-encrypts it. Same function, same key, same code path.

and after each use of the ChaCha20 context, we shall zero it ser this is not ceremonial. The context struct holds the expanded key schedule and the current position in the keystream. Leaving it on the stack would leak key material to anyone who can read process memory after the handler returns.

— C

Circeling back to The demand-decryption engine (A) decrypts a page when the CPU first accesses it. But when does re-encryption happen?

The naive answer "set the page back to PROT_NONE after the function returns" does not work. The handler has no way to know when the function returns. It could call other functions, take branches, loop. We cannot intercept the return without instrumenting the code.

hence x86 Trap Flag.

The TF is bit 8 of EFLAGS when TF=1, the CPU delivers a SIGTRAP after executing each instruction. This is the hardware mechanism behind single-step debugging.

We set TF=1 before returning from the SIGSEGV handler step 9 in The CPU then single-steps through the protected code, delivering a SIGTRAP after each instruction. Our SIGTRAP handler (_trap) checks the current instruction pointer:


    static void _trap(int sig, siginfo_t *info, void *uctx)
    {
        ucontext_t *uc  = uctx;
        uintptr_t   rip = (uintptr_t)uc->uc_mcontext.gregs[REG_RIP];

        if (!g_hot) {
            /* sus clear TF and pass to default */
            uc->uc_mcontext.gregs[REG_EFL] &= ~(greg_t)0x100;
            struct sigaction sa = { .sa_handler = SIG_DFL };
            sigaction(SIGTRAP, &sa, NULL);
            raise(SIGTRAP);
            return;
        }
        if (PGN(rip) == g_hot) {
            /* still on the hot page keep single-stepping */
            return;
        }
        /* CPU has left the hot page re-encrypt and clear TF */
        uc->uc_mcontext.gregs[REG_EFL] &= ~(greg_t)0x100;
        mprotect((void *)g_hot, PGS, PROT_READ | PROT_WRITE);
        _crypt_pg(g_hot);
        mprotect((void *)g_hot, PGS, PROT_NONE);
        g_hot = 0;
    }

TF stand for THE FUCK nah ... The logic is if RIP is still inside the hot page, do nothing (keep
TF set, return). If RIP has moved to a different address whether that is a CALL target, a RET destination, a JMP, anything re-encrypt the old page and clear TF.

This handles every control flow transfer automatically, without any code instrumentation. something like:

    [ibi] SIGSEGV: decrypt page 0x555555559000   <- main calls check_key
    [ibi] SIGTRAP: leaving page, re-encrypt ...  <- check_key calls check_sum
    [ibi] SIGSEGV: decrypt page 0x555555557000   <- check_sum page fault
    [ibi] SIGTRAP: leaving page, re-encrypt ...  <- check_sum returns
    [ibi] SIGSEGV: decrypt page 0x555555559000   <- check_key resumes (was dark)
    [ibi] SIGTRAP: leaving page, re-encrypt ...  <- check_key calls check_product
    [ibi] SIGSEGV: decrypt page 0x555555558000   <- check_product page fault
    [ibi] SIGTRAP: leaving page, re-encrypt ...  <- check_product returns
    [ibi] SIGSEGV: decrypt page 0x555555559000   <- check_key final execution
    [ibi] SIGTRAP: leaving page, re-encrypt ...  <- check_key returns to main    

Three functions, three pages, 10 signal deliveries total. Every cross page control transfer produces exactly one SIGTRAP (re-encrypt old) and one SIGSEGV (decrypt new). The invariant holds throughout.

on performance a single-stepping is slow. Every instruction in the protected code generates a SIGTRAP, which involves saving and restoring signal context. For a tight loop of 1000 iterations, this is 1000 SIGTRAPs per page per loop. This technique is cool for code that runs infrequently license checks, key verification, authentication gates that's it.

The ChaCha20 key and nonce live on a dedicated anonymous page that is PROT_NONE except during the window when it's actively reading it. The lifecycle:

  - Allocated with mmap(MAP_PRIVATE|MAP_ANONYMOUS) and filled with
    getrandom() entropy.
  - Immediately mlock()'d to prevent it from being paged out to swap,
    where it would persist past process exit.
  - madvise(MADV_DONTDUMP) to exclude it from core dumps. This is
    belt-and-suspenders since we also disable core dumps with
    setrlimit(RLIMIT_CORE, {0,0}), but MADV_DONTDUMP survives a
    setrlimit reversal by an attacker who patches the init code.
  - madvise(MADV_WIPEONFORK) so that if the process forks, the child
    gets a zeroed key page rather than a copy of the key. A child that
    somehow triggered a .foo fault would call _die() rather than
    decrypt with a key it had inherited.
  - mprotect(PROT_NONE) immediately after the key is written.

the key page is opened for exactly the duration of the decrypt operation:

    mprotect(gk, PGS, PROT_READ);     /* open */
    cc20_init(&c, gk->key, ...);
    cc20_xor(...);
    explicit_bzero(&c, sizeof c);
    mprotect(gk, PGS, PROT_NONE);     /* close */

There is a brief window where gk is PROT_READ. An attacker who can interrupt the process precisely during this window (via a second thread that calls mprotect or reads /proc/$pid/mem) can read the key. This window is on the order of a few hundred nanoseconds. Closing it completely would require hardware memory encryption (AMD SME/SEV or Intel TME), which is outside the scope of a userspace implementation In other words skill issue.

and On program exit we call

    mprotect(gk, PGS, PROT_READ | PROT_WRITE);
    explicit_bzero(gk, PGS);
    munmap(gk, PGS);

explicit_bzero (or a volatile-loop equivalent on platforms without it) is used rather than memset() to prevent the compiler from optimizing out the zero a real thing since the key page is never read after the wipe in the C abstract machine.

— D

The constructor performs two environment checks before touching the key or the protected section: _traced() and _ld_hooked(). Both are implemented using raw syscalls rather than libc wrappers.

This matters because LD_PRELOAD hooking the most common dynamic analysis technique intercepts libc calls. If we called fopen() to read /proc/self/status, you could LD_PRELOAD a fake fopen that always returns "TracerPid:\t0". Our raw syscall reads bypass the dynamic linker's PLT resolution thingy

    long fd = syscall(SYS_openat, AT_FDCWD, "/proc/self/status",
                      O_RDONLY);
    long n  = syscall(SYS_read, fd, buf, sizeof buf - 1);
    syscall(SYS_close, fd);
    

We scan the buffer for "TracerPid:" and check whether the value is non-zero. This catches gdb, strace, and any ptrace-based tool.

For the environment check, we read /proc/self/environ (again via raw syscalls) and scan for LD_PRELOAD= and LD_AUDIT=. These variable names survive even if the we removes them from the environ[] array seen by getenv(), because /proc/self/environ reflects the original
execve() argument, not the current environment.

We also call prctl(PR_SET_DUMPABLE, 0) at the start of the constructor. This prevents /proc/$pid/mem from being readable by other processes (without CAP_SYS_PTRACE) and prevents core dumps from being written by the kernel even if RLIMIT_CORE is later raised.

setrlimit(RLIMIT_CORE, {0,0}) is belt-and-suspenders for core dumps very simple and clean but be my guest play with it how you like.

Also It is worth saying that

At all times, at most one page of .foo is in plaintext state
(PROT_READ|PROT_EXEC). All other pages remain PROT_NONE and
contain only ChaCha20 ciphertext. The ChaCha20 key exists only
on a PROT_NONE page, exposed for less than 1 microsecond during
any decrypt or re-encrypt operation.

This invariant is maintained by the cooperation of SIGSEGV (which decrypts pages on demand) and SIGTRAP (which re-encrypts them when the CPU leaves). The SIGSEGV handler also re-encrypts the current hot page before decrypting a new one, providing a fallback for cases where a page transition does not go through the TF path (theoretically possible with async signals).

— E

This ain't no panacea, here's some problems for you to chew on. Easy ones, but solid learning material.

.foo shows up clean in the ELF section header table. And even stripped, the PT_LOAD program header for those pages has a telltale alignment, 0x1000, that doesn't match normal .text padding. Fix? objcopy --strip-section-headers and pick an alignment that blends into the surrounding segments like it was always there.

The key lives in memory and someone will find it. Sure, it's sitting behind a PROT_NONE page with a tight access window, but it exists. Any process holding CAP_SYS_PTRACE can read it. One arbitrary-read vuln in your own process and it's gone. Hardware memory encryption, AMD SME/SEV, is the only real answer for protecting in-memory key material from a sufficiently privileged attacker. Userspace can't save you there.

The Trap Flag trick is old news. Setting it is a known anti-debug technique and aware debuggers, LLDB with the right scripts for one, handle it without breaking a sweat. Don't lean on it like it's a secret.

And some to find on your own ..... and solve.

Source code

H4sIAPKCNGoAA+097XLjRnK6q0qlzPxOKvk3ln0rQPxYAARBainqQkvctcpaSUdxvd7IMgoCQQol
EqABUEd5V3mO/M/T5EnyAHmBdA++BgApSvaSd5bQuwKBmZ6emZ7unp7GDFlRR6Y1nW2sEgRBqNdq
hH4q/qcgyf6nf18lYk0Sa6IgVmsKgWu1LmwQYaWtCmDqepoDTXENfeqY3u0iPEAbDO6h43eFRJ+/
F/iHf/nHjT9ubLzVdHJyRn4gAWDaxhfwJ8Hfz/CHz//9MJLtXq8b3GKJ/4K/f0qh/CFO/2fdHle0
yWRkVCaOfWNYmqUbG3/448b1//zr/7n/u/Fvn6GTOSyCU232raH1Defl6uzAUv0XhZT+10RR2SCr
tUoBPHP9rwpk7JljoyXWG2JDUqSGUhHlek0W4K5Qq5Ojw2/a3f1vD7/vVGaa5zmVeeraav/lsK01
rj80qqdW+5vrgrxDzqDQ0Yf7CjE6Xvhb8+G5AtX6l6utY5n+o76k5n9JAv2vrbZZPjxz/ffHv6I6
UwvNQEVfQR3AD0WWH+b/iYqE9l9S5Nz/Wwvk/t+zBl//Yy9wFXZgqf4z/p+v/3VBlHL/bx2Q9v+A
/5W6LFXrdbkm5f7fkwdf/1c5+y/Tf1B2SUrP/0JNyuf/dcBXfWNgWgZR3xy/U89O3nX3O4WvTEsf
TfsG2XVv3ZfjsWZVrvZSqRNH90bZZPjTtdGcDMdw7amjG6kcc2hpKeypblueMfOSqQPdytTnOaY1
TKf1TcvLpI3My1QllgnJibRN/UqD/5JQudosFEK+nL45I7Kwo7w7YpKOOY3nuCnUNPEc1ePhkbwg
/8khcpmIPB/hvm339r/lJiVilIjLkx8L6FtxnGv+YmA5zuDL3ITnyV6LYJo94Fy+LJIXL8iXqno5
NUeeaaljY6yPJxwgliC7xCBCTQVgleFYBJrukIFtqyjP3vlFiT4YVv/8olnwbicGtIgAy6a6Rz4S
bHtD9ci1cXtelS6aUYJlg2U+FzHpjpiXpgoYzUIBiHqmTm5ss09U3bmdeOpkGHOATIZ8M0QKShGy
PbyOEmPUoXple3PTscGXmgus8u89ezIXz7A851Z1XMhlGP2D2vmhs0/kRlgk0Vm/7MgukSsTuwZU
ZoaujrXJeVj0Iu6BhdVYiJHue980OLzjCx/pWJoDwtEe8cRPQBjDJOcZusdRVLLNU4wSChNcuic9
tdtpH5BP/v377mGvA+wLS8f89Qk3H0H3+OSYJUXzSYsIftJd3OTrue0dXj+0kcZsMjJ101MvfzEc
OyzItnVqAXPnZAyvoUHH746O2DbBaJgeJwLaXYrhfzUnWY5/ie13DG/qWM3f6zA8kun3MnwusxlG
p5k6X4MDBuu6JKi6NyN6c1lDg5poCdOCEXyhg/Jel/dA//0bak9KRGAxXcO4ppiTIZjLWO9ZnJnt
UBQuNEzb/GQIjzA5uB5JJsZdTjEJCfjWkuj8vZ0JBizmE5oA1XM03egnpI+a2cvp4FwS5MaFT3Nk
W0My6AO3g+mPO/twptoTcHNBKto99fXB/vuDEtmEWdPWX7rGaPASq5m6myVyonYPTo6PPvCxIAOp
XeBYIOCh1NBarFQlDqzawNLDH7QJ2INIPBf0GZL86cgnwJbTRzba2UGfqdYiu61stQPbCblO+749
gSbQyrYN/44UidUkE2izAR/FIquCSJedAzd7yFLn1Oy/2uRZRMpbppafgfYEKItCM4Hz1ytzZBDu
Z6wNp0kOMVtkC/59+kSChx+9LSD+c7GYLBt0LCoL2F8CtrAVo90xChrzISUWoz7os329SDLQXfgN
kmFYN6ZjW09ONO4Vi6MD9bTbOTppH7Q2eRzJdG773cFhD/L4eSMqxgMYyMckGuMJjzIZI0QPiwfZ
t5EjW+ujf+DOH+WGuCP9hlFGwg8Z4r/JAPvp2EvrgqA+oYrcO+RNvAN2B14T9CD0qpqEHXjWFcMJ
Ed2xeGJkBtAnB1fU0PJW2lTQ0tBjsrtLZBAYwnrjUAp6s7WzRf6MFMqo4uRVcKttUavCJ01DQkTu
EnKKXQzakMCa11CSaSjtHgfXtTWUpBuKNosOSoLPdCQxy+c/fEADg66wHYKcYrFE7XqiIUyNM6gx
qCCriQlyP1qZxsVk5mci4TRTGec9ELiLCpWIkd1cikhHBBYBKUSam2XuXdr4w3oMMRnPSev3ndA8
zONquJJARvKJvmFJXPoxzTRpT4BjNG83lXVl3mf/FtsycGQmtFmw4EaXaGhaAxv9J/ws+UjbsFia
hf3wbR4gNoNbRPRrCdfnWHyKY47lgqyIJ46JhoGR9ale3ptCP8LF/dAxhu55t/NG7R6eXmSKuw8v
fobFmZVBehWwuGjn9dEFedGChTumQS3CTBQYFQkWkMAFTfdM2yKuBq36SCqupl5pVn9kOPB8dvhG
PXh9RO6YgmEJDjJ73fZpibxwtRJ1xhl9djTTNUIUNp0xwvGSDcMOwFYedcXvZKZA4df399evleav
kx61RmLWR1F3UYKoaoSrA1QKTNyNowMLOEDlIFJU5BnvL9x5BoEJI1DK8LHHxhZi2ixma552ucbw
5ldq18M1aqBNR8gjFANGMbCK8p5rqtQKMf3z8XdZBoJb5adGfEUeMqryeQT+rPPm+yUCjygLBZ7V
5Xg45joR22lDAYK2zFRkqUD1wAmgs01jSiECjujAscfIKYK1BHhZqfTTWcGcQwUbA1RiuaSlWEzs
clQhhgCjcrH8sshMdlJGGfmIenTHij6qG/XW8AYmZioWf3ehk7v5loQ29nGWye/fAst0Lz10YVNW
iuI/zNh+Anvh29i0zVDxtZh5OfUMVeV8jxp1z3bQVmEElYZT2JUHjbhzp131rNNTD969PW1/c9SJ
Iyuu4TkjcwyFukeHbw976v5JF7JfcIFS+5n8R3C5hTvWUIRRDj4pZDQrXummTSijARmbFEWhI8YF
akGyuFwQpfYXK+DxwjAEVTArsKhWDGmNMdSFluVeGSglHCWAt+1TWGMeft/udcgn+tQGWfvw9uQd
0CiLMSf9+ChOs4j0un141DngmQhliDMe2fp1FHNDNYIF1MdMLC4uGQq01r9BOxhFoN62D75XYRnY
w1ENpXQu0vvD087J8euT7nchR9iF3RBEAKy0PWZicFWJEZHFuEGYTgywKbrm0YbTCGyYNkd/50Tt
E1G9JUpKPWY2DElY89rEBMaw0udii3J2jrmhryF+WzsD+0Op+GU1Ou8yUocTWO+7s/94sOj9CgGk
lSYl8AGiFYulhiYtbGhGOJO5zYfLbKLg/ZI7DzUhv1QkwXEYeWAsoMloquATjAJ6HK5KpzJKhT6Z
vxi+80EJkrvIu/AJZV2XoDnGGEwjR90RIQoHu1rcAGM88W4DHPR0xpp7zTSv30/l+b2KPZjFSIxf
7+cMRtrQxV60Vcg+BE6AJMDDyfFZr73/XdgXiht3peW7mHFtS1ytOeVxATinfHZtcpfvxHhWEO7/
hOkapoTVbAB5zP5PuNL9H4qS7/9YC+T7P581pPd/rsIOPGb/p6//iiLK+f7PdUBm/2djp6LUhR0w
wEoj3//55MHX/1XO/kv1XxQUMaX/slLLz/+uBZJbJ+3kjshwWzBuiHx9ckJjmfqVAWs0dzpOvAZ2
o91ZgIJBY/dcuChvCVslckmfRPqUeE/FaaRILun7jBr5MxHIK3yRdZeuCgxGH5Z2i6vTaQVSUB19
DX9enVOdTrZJn1YH883i+q6N2/l1BXRiBrj4PjfZSNffRITUxppp0bcCoFt6KSAG9zfnF+xWNswl
u0Rio68TB8oNuM2pqw2NV+RPLtmFVu39iJtCKAXhIhM9D18C3kV8wVh93CVaTgzLhTXgPk3ThRoo
bQfYsnlrTDaBNZuWdrXJJzjo5MvDJwfh+i/a/LyCOeBx6z+6/x9mgNz+rwXy9d+zhvT6bxV24HHr
P4mu/+r5+m8tkF3/KRWlJtckWaxX8/Xfkwdf/1c5+y/V/2q9ltZ/uV6t5/P/OmD+8bd5h+yio1bd
k6OqxN2ULJ5wHHfD7+5yFs9/wtu9Pa4qlfERT6aFBf7S5bTSZUkv9cMTcFqxddkk/Z9aGlxbPsF+
SVT4ZoCgF1v9Jrn8qaXDNUC4LIlShDCfAmksoUDqfGojxiV9XYovoKuS6hF76p2LykWJxAdNaLqL
qeEaLUqdYWr0nlGf3HKzEnFLRJHZt9up/aCi4G8FZRZ8wKEZLOpKs3MZL6SBV1FiV3kURcT0GkXZ
oSjVDIqE6QrNpARFOYNSxfQ6zaQExVoGRYgqCqhkUcS4InFBc6WooqBH2eZW407vJJt7t5iBSsBA
HCwTd6jP8KMIg2ReJE9rjFD+ouFSRwZIQeoIUbS1LIwThOj8BNiAO7bZFPFid7fBbMJNZUuQDWKc
Tq5CsiT7sQEqdvGJqei01bbOCh1zODOdHB3RLMU90z0n7EbQ92QZ1xyONRRWYNamMZtoVp+Apl7e
ega53vQZrpf3MGqDr4spn2iZogAaRXPEdE4o4zRXSuc2wnLVdA5q8cKxbQRDS4vKRTMujKGKIjG3
E9WKtF7oPZvG1Eh5VRQSReR0dpJiLZ3diLMnNr69V+TUQNIDbYmBRL4rMjAeOazag0HGdFyOrsOd
elRIuBCTvIzNBw3jGGNEhFsG508xDsMHoBnvIIFy6U2TtGJvPImtFkJgAiG9RImx2/V8owap9IgJ
RYkqTvAEakuk0iZFR22IMXINpjEJVvrKnmAonv7L8JNqK6h8Wh+2Tcvf14GnSgwr7DSVriCZETDA
yJhfZFfYJGxT+rzBYt4t4d+DeDiPYxlGMdvS41Mfkf0zLfz8ifiVnPulisWLmLmL5v8w/vNWu4bJ
emSswsd4VPxHEuj7//z7P9cEefznWUM6/rMKO/Co+A/Vf0XJv/9zPZCJ/+xIFUGqykJDrMl5/OfJ
g6//q5z9l+t/FTKT+i8rtVo+/68D9vf9+b5Fhrpe2H991H5zhk/lE4mU32ujEVyNmedopDyw7DLd
oV0ONteDg10e3JiueWmOgHOtK7PfN6zC0YFPBYi8H5XKvRLkV0Z9/6mMX2rUL5v9FiyuDFJ2CwV/
88krEm5CIdG3kZE4Lln44mtuf58ncKXU8S6oiCdlm3z97+TrnwoFfWRo1qvCF84YmhZQzG3LPRD6
//4YraaOx/n/NP5bE/P3v+uB3P9/1pD2/1dhBx7n/9P3v5Kcv/9dC2T9f7nSUOpSTdmpirn//+TB
1/9Vzv4P0P96Zv6vCvn3v68Fzjr7vcOT47Mg4l3Brx54RdpHh2+OOXp0XWCD4d8eHhx0jrnogDf4
+BUmkr3NYXk+9VzZjlMqUCJBvDmPNp4Hjylj+Prw+KzT7ZH2616nSyp41L6Zm4zPAenff7haQR2P
8f/FOo3/S3n8f02Q+//PGhb9/sPntANL9V+op/S/Dvm5/78OkHbSv//QqNSrilzbkWq5+//0Ifn7
D6uY/ZfrvyjJ6flfqIn5/L8O+GriaMOxRnCnU7xjE0/Epb6iCvhDvzVkE136Tb5EtJE5tIw+h193
DI+W7e+24/lcmX9HkDn/tQIT8Kj4v+D//mctj/+vB3L//1nDwvNfn9EOPCr+T/VfqQu5/78WyJ7/
kiqSIMhKbadWzxcATx5S579WsgBYpv+1qpLSf7men/9eDyT8/6W/owbLA3oULP17YsmjDW68Rz7c
o4+70hX5Ij7VMLHdZuEu+q2h5grPxTQfeVKj+bkOIuSvKHLIIYe/Z/h/c1M/EwCIAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
- http://phrack.org/issues/61/8.html
- https://man7.org/linux/man-pages/

To comment or discuss this post, please join us on the 0x00sec forum.