Brady Bunch Boondoggle Redux – Answers and Winners

| July 17, 2009

sam-opening-pic.jpgAll of the answers from Brady Bunch Boondoggle, the Skillz H@ck1ng Challenge from February 2009, are revealed as we continue our story with Oliver and Mr. Brady discussing the packet capture of the kids’ hacking activity.  While pondering who could help them with the analysis of the data, a bright light flashes with a rumble that shakes the house.

Oliver asks "What happened Mr. Brady?"

"I moved the island Oliver.  We’re 3 months in the future now."

"Oh … OK.  Who can we get to help us analyze this wireless packet capture?"

At the backdoor, a voice calls "Did someone say wireless packet capture?"


The Technical Winner, Creative Winner and the Random Winner are all listed at the end of the article.

Active Image
Active Image del.icio.us

Discuss in Forums {mos_smf_discuss:Feb 2009 – Brady Bunch Boondoggle}

 redux.jpg

By Joshua Wright 

"Come on in Sam", Mr. Brady calls, "do you know a thing or two about analyzing wireless data?"

"Sure do, I was a Wireless IDS analyst for the VeriWorks Managed Security Operation Center before working in the meat industry.  What do we know so far?"

"Last week Mr. Phillips had an audit team assess the office for wireless threats.  We have a screen-shot from the Kismet tool here."

phillips-audit-kismet.png 

After a few seconds of analysis, Sam shared his thoughts with Mike and Oliver.  "This Kismet screen-shot gives us lots of useful information and I can say that the kids’ AP was not active at the time of this assessment."

"I’m sure Greg hid the AP before this Kismet screen-shot was taken.  Could they have escaped Kismet
detection by setting the AP to not broadcast the SSID?" Oliver asked.

Sam responds "Not a chance Oliver.  Using the monitor-mode feature on wireless cards, Kismet sees all activity in the area.  Even if the AP didn’t have any users connected, it would still send beacon frames at a rate of 10 per second.   We can see that this Kismet capture lasted for 28 minutes in the bottom-right corner, so Kismet would have seen some activity from the AP, labeling the network name as ‘<no ssid>’."

"Could it have been hidden in the ‘Probe networks’ group instead?"

"No, that list is for client devices that are actively probing for networks.  Let’s turn to the packet capture data to see if we can figure out how they evaded detection."

Copying the packet capture to his IMP-16, Sam starts his analysis using tools from the Wireshark suite.

IMP-16 $ capinfos bbb.dump
File name: bbb.dump
File type: Wireshark/tcpdump/… – libpcap
File encapsulation: IEEE 802.11 Wireless LAN
Number of packets: 223242
File size: 30875409 bytes
Data size: 27303513 bytes
Capture duration: 985.819307 seconds
Start time: Thu Jan 29 09:55:08 2009
End time: Thu Jan 29 10:11:33 2009
Data rate: 27696.27 bytes/s
Data rate: 221570.12 bits/s
Average packet size: 122.30 bytes

Note to the reader: Yes, the date stamps on the packet capture do not come from 1974 when the IMP-16 was introduced.  Please don’t get hung up on this.

"Well, for starters, this is a fairly large packet capture.  Wireshark is going to have a lot of delay when applying filters and reloading data with this many frames, so I’ll create an extract of the first 1000 frames to focus my analysis on the events leading up to the hack with tcpdump."

IMP-16 $ tcpdump -r bbb.dump -w bbb-1000.dump -c 1000
reading from file bbb.dump, link-type IEEE802_11 (802.11)
IMP-16 $ capinfos bbb-1000.dump
File name: bbb-1000.dump
File type: Wireshark/tcpdump/… – libpcap
File encapsulation: IEEE 802.11 Wireless LAN
Number of packets: 1000
File size: 96573 bytes
Data size: 80549 bytes
Capture duration: 62.714862 seconds
Start time: Thu Jan 29 09:55:08 2009
End time: Thu Jan 29 09:56:10 2009
Data rate: 1284.37 bytes/s
Data rate: 10274.95 bits/s
Average packet size: 80.55 bytes

"Ok, let’s take a look at this smaller packet capture in Wireshark."

Studying the first few screens of packets, Sam says "Boy, those kids sure are sneaky.  Take a look."

bbb-redux-1.jpg

"We start to see activity from an AP with the source 00:1a:70:fc:c0:6f in frame 8, 27.5 seconds into the packet capture.  This is very unusual; only an AP would send a probe response frame with any legitimacy, and we would normally expect to see beacon frames sent at a rate of 10 per second from an AP, even when it isn’t actively used by any wireless clients.  We also appear to be missing some data, since the first frame from this device has a sequence number of 1, not 0."

Oliver asks "Could it have been a problem with my wireless card capturing the data?"

"It’s not unusual to lose packets while capturing in monitor mode.  Your wireless card capturing the data could experience interference, such as traffic from a nearby Bluetooth interface that would cause your view of the frame to be corrupt but otherwise valid for the active connection.  Always keep in mind when looking at a packet capture, wireless or otherwise, that you might not be seeing the whole picture."

After another minute of analysis, Sam continues to unfold the details of the attack. "What is most interesting is the activity that continues after the probe responses in frames 8 and 9.  We see the AP suddenly start to beacon only after sending probe responses, which presumably followed a probe request that we don’t see in this packet capture.  The first beacon frame from the AP gives us a lot of information about this device."

bbb-redux-2.jpg

"The ‘DS Parameter set’ field in the beacon’s tagged management information elements list tells us that the AP is on channel 11, which at is 2.462 GHz.  We know the kids didn’t try to hide the AP by using a 5 GHz or otherwise uncommon frequency.  The SSID does appear to be hidden, replaced here with ‘00′ or NULL bytes for each letter of the probed SSID – 10 NULL bytes corresponds to the 10-byte string ‘boondoggle’ seen in the previous probe responses.  Also, the BSS time stamp field is very small, 0×19185.  This field is used for time synchronization between the AP and all the clients on the network, and is incremented by 1 for every microsecond the AP has been online.  We can use this value to determine how long the AP has been online by converting it to decimal and dividing it by one million, the number of microseconds in a second.  The value 0×19185 in decimal is 102709, divided by one million … this AP has been online for one tenth of a second."

Mike asks "Could one of the kids have used one of those new APs that turn on at a specific time?  That Peter, he’s mighty clever."

"It’s possible Mike, but I think it’s pretty unlikely.  The timing of activity from the AP and the activity from the wireless client at 00:19:7d:1b:03:fa seems fairly coincidental from a timing perspective.  No, I think this is what happened…"

"In frame 8 we see a probe response from what we would later know is an AP at 00:1a:70:fc:c0:6f (we know it is an AP when we start to see beacon frames from it in frame 10).  Frames 7 and 8 are both probe requests to the broadcast address from the station at 00:21:5c:7e:70:c3; I think we are missing a frame between 7 and 8 which was a probe request for the SSID "boondoggle".  Since we know the network is cloaked, and the AP didn’t respond to the probe requests sent to the broadcast SSID in 6 and 7, we can deduce that "boondoggle" is the correct SSID for this cloaked AP."

"Only after the missing probe request for "boondoggle" do we see probe responses from the AP with this SSID.  What is most interesting is that immediately after the "boondoggle" probe responses in frames 8 and 9 we see the AP start to send beacon frames.  Let’s look at the decode of frame 10 for additional details."

bbb-redux-3.jpg

"Hmm, a few things of interest here.  First, the beacon interval is set to 0.1024 seconds; this indicates that the AP beacons at a rate of approximately 10 times per second, which is normal for an access point.  If this AP were beaconing at the time when the PCI analysts were analyzing wireless activity, Kismet would have recorded this device as an AP."

"We can visually examine the distribution of beacon frames using Wireshark’s IO Graphs feature.  I’m going to click Analyze then  IO Graphs to open the IO Graphs dialog box, then enter a display filter to graph only beacons from this device using ‘wlan.fc.type_subtype eq 8 and wlan.sa eq 00:1a:70:fc:c0:6f’.  I’ll change the X Axis pixels per tick to 10 to make it a little more readable and viola!"

bbb-redux-4.jpg

Mike adds "That’s pretty swell Sam, but what does this tell us?"

"Well, we can see that the AP doesn’t start beaconing until a little more than 27 seconds into the packet capture, which corresponds to the timestamp we see in frame 10.  After the initial beacon, we see a steady rate of 10 or 9 beacons a second, which corresponds to the beacon interval of .1024 beacons per second.  This picture tells us that the AP behaves as we would expect immediately after frame 10."

"We also know this is a Linksys access point from the source MAC address resolved by Wireshark as ‘Cisco-Li_fc:c0:6f’.  We can also see a vendor-specific information element labeled ‘Broadcom’ in the frame payload, indicating the wireless chip used by this AP is from Broadcom Corporation.  If it’s a Linksys AP with a Broadcom chip, it’s probably a variant of the Linksys WRT54G line of products."

Oliver chimes in, "It’s a very hackable AP!"

"That’s right Oliver, and it reminds me of a project released at Blackhat Europe 2005 by Oudot Laurent called WKnock.  Oudot wrote some code for the WRT54G AP to run in the OpenWrt environment, using the wireless card to sniff in monitor mode."

"And when in monitor mode, you don’t generate any activity that can be observed, right?", Oliver asks.

"That’s right Oliver.  The wknock code listens in monitor mode for probe requests with a predetermined SSID.  If wknock sees a client probing for the configured SSID, it will switch from monitor mode into master mode to become a fully functional access point.  Here, let me draw a picture.  Oliver, pass me those markers."

wknock-illus-small.jpg

"Let me see if I understand this", Mike says.  "Before Peter showed up, and during the PCI assessment, the AP was there running wknock, but since it was in monitor mode, it wasn’t generating any traffic."

sam-meatloaf.jpg"Right-on Mr. Brady", Sam replies.

"Then, when Peter’s workstation sends a broadcast probe with an unspecified SSID, wknock ignores it since it doesn’t match the secret SSID.  However, we think Peter also sent a probe with the SSID ‘boondoggle’, which matches the secret SSID for wknock, causing it to turn the WRT into AP mode, giving him network access."

"Correct again Mr. Brady.  After a little while, wknock returns to monitor mode to evade detection."

"I’m going to have serious talk with that young man", Mr. Brady fumes.

"Now, now, maybe you’re just making a meatloaf out of a hamburger", Sam jokes.

"Was that meat humor?" Oliver asks.

"Maybe you’re right Sam, what else can you tell from the packet capture after the Peter got connected to the network?"

"Wireshark has a great summary feature where we can look at all the connections between hosts.  For this, I’m going to switch back to the full packet capture file.  Once that opens, I’m going to click Statistics, then Conversations.  Now, this is going to take a while for Wireshark to decode.  While I’m waiting, I’m going to visit my favorite little filet … oh Alice, are you there?"


Returning to the Wireshark conversations Window, Sam continues his analysis.

"From the conversation summary information, we can quickly determine what is happening with the packet capture.  Navigating to the WLAN tab, we can see 8 conversations are present, with the majority of the traffic between Peter’s workstation at 00:19:7d:1b:03:fa and a VMware station at 00:0c:29:fd:a6:66.  The results get really interesting when we click on the IP tab."

conversations-1.jpg

"Sam, I can tell you that the host at 172.16.0.98 is my Gentoo workstation.  My boss Mr. Phillips’ Ubuntu 7.10 workstation is at 172.176.0.99.", Mr. Brady adds.

"The device at 172.16.0.6 must be Peter’s host then, and it looks like he spent most of the time communicating with Mr. Phillips’ workstation.  Let’s take a look at the TCP conversations, that’s where most of the activity is."

conversations-2.jpg

Quickly reviewing the TCP conversation data, Sam starts to form a hypothesis for the events as they unfolded.

"There is a lot of activity between Peter’s and Mr. Phillips’ workstation that are 1 or 2 frame conversations with varying source and destination ports.  This is likely a TCP SYN scan between the hosts so Peter could determine what services were listening.  However, toward the end of the list, the majority of the activity is between Peter’s host and the SSH service on Mr. Phillips’ machine.  In fact, a large number of the conversations terminate after 20-50 frames."

conversations-3.jpg

"Is that unusual?" Oliver asks.

"Most of the time, SSH sessions will last for a large number of frames, for an interactive terminal session, or for transferring a file or some other administrative task.  Only 20-50 frames in a SSH session is slightly unusual, but a very large occurrence of this small number of frames is very unusual.  It’s almost as if they were trying a brute-force password guessing attack against the host."

"Sam, I can tell you that password guessing would not have worked, we use public key authentication between hosts at work."

"Wait, Ubuntu 7.10 and SSH public key authentication?  Why, that’s got to be the OpenSSL Debian PRNG bug!  In 2006, the Debian team modified the OpenSSL source in what they thought was an uninitialized variable bug.  This code was distributed for a few years before anyone realized, leaving all generated SSH keys vulnerable to a brute-force attack.  Using precomputed key values supplied by the Metasploit project, an attacker has to make, at worst, 32,768 guesses before getting the correct key.  With the large number of small SSH connections shown here, I bet that’s how they got in.  Also, take a look at this last entry."

conversations-4.jpg

"The last entry in the TCP conversation list is for 3254 packets, significantly more than any other connection."

"I guess we’ll have to do some forensic analysis on Mr. Phillips’ host to figure out what the kids did after they got in then", Mr. Brady adds with a sigh.

"Wait just a minute there Mr. Brady, I don’t think that will be necessary.  The kids used the OpenSSL bug to get access to the system, but we can use the same bug to decrypt all the traffic.  I was reading about this a while a back while searching for a good sushi restaurant, just a sec."

Turning to Google, Sam uses the search criteria "decrypt debian ssh".  His first hit is "Decrypting
Debian-Vulnerable SSH Traffic" at www.willhackforsushi.com.

"This blog post describes just how to take a Debian vulnerable OpenSSH packet capture and brute-force the OpenSSH Diffie-Hellmann key exchange to decrypt the SSH traffic."

"Wow, what a swell guy for posting that much detail in a step-by-step format", Mike adds.

"Yeah, lucky for us.  Let’s see.  First, we need to make a packet capture extract of the frames we want to decrypt.  Since we only care about the SSH exchange with 3254 frames, we can right-click on this entry in the conversations window and select Apply as filter, then Selected, then A <-> B to limit Wireshark’s display to just this TCP connection."

conversations-5.jpg

"Once that filter has been applied, we can save the results of the display filter as a new packet capture file by clicking File, then Save As.  In the Save As dialog box, change the Packet Range selection to ‘Displayed’, then enter a new filename and click Save.  I’ll call it bbb-ssh-extract.dump."

"With the packet capture extract, I’ll setup my system to decrypt the traffic."

IMP-16 bbb $ wget –quiet http://www.willhackforsushi.com/code/wlan2eth/wlan2eth-0.1-
src.tgz

IMP-16 bbb $ tar xfz wlan2eth-0.1-src.tgz
IMP-16 bbb $ (cd wlan2eth-0.1 && make && cd ..) >/dev/null
IMP-16 bbb $ wget –quiet
http://downloads.sourceforge.net/sourceforge/tcpick/tcpick
-
0.2.1.tar.gz?use_mirror=iweb
IMP-16 bbb $ tar xfz tcpick-0.2.1.tar.gz
IMP-16 bbb $
(cd tcpick-0.2.1 && ./configure –prefix=/opt && make && sudo make install)
>/dev/null
write.c: In function ‘avail_filename’:
write.c:141: warning: incompatible implicit declaration of built-in function ‘strndup’
IMP-16 bbb $ wget –quiet
http://www.cr0.org/progs/sshfun/ssh_kex_keygen-1.1.tar.bz2
IMP-16 bbb $ tar xfj ssh_kex_keygen-1.1.tar.bz2
IMP-16 bbb $ (cd ssh_kex_keygen-1.1 && make && cd ..) >/dev/null
IMP-16 bbb $ (cd ssh_kex_keygen-1.1 && wget –quiet
http://www.willhackforsushi.com/code/ssh_decoder.rb && cd ..)

"Next, I’ll convert the wireless capture to look like an Ethernet packet capture for tool compatibility, then I’ll split the data into client and server traffic exchanges and attack the Diffie-Hellmann key.  Watch!"

IMP-16 bbb $ capinfos bbb-ssh-extract.dump
File name: bbb-ssh-extract.dump
File type: Wireshark/tcpdump/… – libpcap
File encapsulation: IEEE 802.11 Wireless LAN
Number of packets: 3254
File size: 451998 bytes
Data size: 399910 bytes
Capture duration: 416.153228 seconds
Start time: Thu Jan 29 10:04:33 2009
End time: Thu Jan 29 10:11:30 2009
Data rate: 960.97 bytes/s
Data rate: 7687.75 bits/s
Average packet size: 122.90 bytes
IMP-16 bbb $ tcpick -wRC -wRS -r bbb-ssh-extract.dump
Starting tcpick 0.2.1 at 2009-07-02 09:21 EDT
Timeout for connections is 600
tcpick: reading from bbb-ssh-extract.dump
1      SYN-SENT       172.16.0.6:44388 > 172.16.0.99:ssh
1      SYN-RECEIVED   172.16.0.6:44388 > 172.16.0.99:ssh
1      ESTABLISHED    172.16.0.6:44388 > 172.16.0.99:ssh
1      FIN-WAIT-1     172.16.0.6:44388 > 172.16.0.99:ssh
1      TIME-WAIT      172.16.0.6:44388 > 172.16.0.99:ssh
1      CLOSED         172.16.0.6:44388 > 172.16.0.99:ssh
tcpick: done reading from bbb-ssh-extract.dump

3254 packets captured
1 tcp sessions detected
IMP-16 bbb $ ls *.dat
tcpick_172.16.0.6_172.16.0.99_ssh.clnt.dat
tcpick_172.16.0.6_172.16.0.99_ssh.serv.dat
IMP-16 bbb $ cd ssh_kex_keygen-1.1
IMP-16 ssh_kex_keygen-1.1 $ ruby ssh_decoder.rb -s -n2 ../tcpick*.dat
 * read handshake
cipher: aes128-cbc, mac: hmac-md5, kex_hash: sha256, compr: none
 * bruteforce DH
DH shared secret :
480a7ee6d32d09fb5a6a931ba0fca33e5adf3b853f3e1f18a49f555c2f693a47c08f5a1aa39c25a66ec3962cd
0d2e0d0dd43ef72a62f6f6ed15c731698c0c0171bfd80bcc53ea2c0d7eefbd0a035ac6afb468a359159a4a497
0e602b7710ca599173157709d28ed7649764ac87dc5fc2f90f9f67092a89b7ac04f1bd640ad619
 * derive keys
 * decipher streams
 * successful authentication packet
{:testic=>1,
 :username=>"mphillips",
 :keytype=>"ssh-dss",
 :key=>
  {:type=>"ssh-dss",
   :g=>
   
"0027323331+m313r337361e212314=206/245rr346z/z21602226102302260^
337-
34r21ve276250Q300*250243217320o2333300202374+374373220QbO346225
272330253374374310253&355f203321s26Q312)223306314275224336264y3052
62]35226203I333]206Y~l360266366t204333b\367!313252177327T231331m,247M
244273u27001313310",
   :q=>"003556300aXn22130524424316J201q374277226`=317",
   :p=>
   
"00345353k27136j20203o311U355335*261330zE33735432602255$371372246
r252s202277226370236m347300257V315242373b004243204260
t[U360254211220&36216%320x9262o177~3523;225fAa21vZl315323317A20330
4250321365212374<253/v$O0@351Z230307p262245251P31bn371263Hb260256204)
24]02251R177~Ui",
   :y=>
   
"v20206271s,t235k31t210C<205$9354@27^2645303323217333330b?215930
2245227XnBQd217277N27021526337/02202226357f:335\333351^264(32267$l
t6365oQ324203;p212?337316WB353303250203Qf36c310314,%236v317t24’237′j
237l304"j330cB30CAr276d304?270177L226203t333]366"},
 :nextservice=>"ssh-connection",
 :auth_method=>"publickey"}
 * deciphered streams saved to "sshdecrypt.0.client.dat" & "sshdecrypt.0.server.dat"
IMP-16 ssh_kex_keygen-1.1 $ ls -l *.dat
-rw-r–r– 1 sam     sam     10155 Jul  2 09:25 sshdecrypt.0.client.dat
-rw-r–r– 1 sam     sam     32349 Jul  2 09:25 sshdecrypt.0.server.dat

"Now we can take a look at the SSH decrypted session data from the server.  The data is decrypted, but the SSH control data is still present, and I assume some more dropped traffic as well, so it’s not perfect to look at.  To remove some of the control data, we’ll use the strings command out the output file."

IMP-16 ssh_kex_keygen-1.1 $ strings sshdecrypt.0.server.dat | more

"Hmm, this looks interesting.  Take a look."

ssh-session-1.jpg

"We can see the normal login content from Ubuntu and a banner indicating the last login time.  After he gets a prompt, we see the output of normal new-system reconnaissance commands, probably ‘whoami’, ‘id’, ‘w’ and ‘ps -ef’.  What is most interesting is the string ‘In the office’ though, with two names."

"Those guys work in my office Sam", Mr. Brady says.  "That Ed Skoudis, he gets started really early every day.  Josh just never goes to bed."

"Well, that output would certainly pique my interest on this system.  If it were me, I’d want to look into that some more."

Sam continues to review the contents of the decrypted SSH session, looking for clues.

"Looks like Peter started to poke around in the files in the home directory next, looking at the contents of the .bash_profile and .bashrc files.   Look at this."

ssh-session-2.jpg

"Here we can see he is definitely looking at the .bashrc file, and it looks like a standard, unmodified Ubuntu .bashrc file, except for the line ‘php bin/atwork.php’ at the end.  This is probably the part of his startup script that shows him who is in the office each time he logs in."

ssh-session-3.jpg

Sam snaps his fingers, "Yes indeed, here we go.  Peter is looking at the atwork.php file, and we can see a little PHP script to connect to the host at 10.10.10.10, login with the username and password root/Ph1ll1psD3s1gn, connecting to the payroll database.  A simple SQL statement is used to get a list of people who are logged into the office."

"Oliver, can you write down that username and password for me, I … just want to save it", Mike asks.

"Sure Mr. Brady!" Oliver happily obliges.

Sam eyes the pair warily. "Okay, let’s see.  At this point Peter has the root username and password to the payroll database.  What’s his next step…"

ssh-session-4.jpg

"Looks like he tries to connect using the ‘mysql’ client, but it’s not installed on this host."

"I hate it when that happens", Oliver adds.

"Yeah, me too kiddo.  But look what Peter does next.  Looks like he changes to the /tmp directory and creates a script of his own.  Looks like a simple interactive MySQL client that accepts SQL statements on standard input, executes them and displays the content, all wrapped in a while loop."

"Wow, that was an awesome idea", Oliver yells.

"I’ve never been more proud", Mike adds.

"Yeah, that Peter, he’s a pretty smart guy", Sam adds.  "From here, it looks like Peter uses his quick MySQL client to connect to the payroll database using the root credentials, then pokes around the database until he finds this."

ssh-session-5.jpg

"Looks like it could be the result of a SQL query with a comment about a raise.  I think Peter changed it so your salary would be 185,000 Mr. Brady.  Why would he do that?"

"He did it because he didn’t want Mr. Brady to lose his job", Oliver confesses.

"Lose my job, why Oliver, why would the kids think that?"

Emerging from the kitchen, having snooped on the entire conversation, Peter emerges.

"Sorry Dad, after disrupting your meeting with Mr. and Mrs. Calderone, we were worried you were going to lose your job and then lose the house if you got fired."

"Peter, next time, come talk to me about your worries.  Mr. and Mrs. Calderone called the next day and said they were so impressed with me as an architect and as a father that they were thrilled to have me work on their new hotel.  I’m not losing my job, in fact, I’m due for a raise as far as I can tell from your little operation here."

"A raise Dad?!  Oh, that’s swell!"

"Yes, but not until after you return my salary to what it was before.  Then we can talk about punishment."

"Ok Dad", Peter mopes as he heads off to revert Mike’s salary.


An hour later, Peter returns to find Mike and Alice sitting on the living room couch.

"Come over here Peter, we need to talk to you", Carol calls.

"Now Peter, you know what you did was wrong, but you showed a lot of skill and determination, especially with that MySQL client script."

"Thanks Dad", Peter replies.

"So, I had a conversation with Sam, and he pulled a few strings with his old colleagues at VeriWorks.  Tomorrow after school you’ll report to work in the penetration testing group."

"Really Dad, I get to work as a penetration tester?!  Oh golly that’s swell!"

"Yes, you’ll start working as a penetration tester, where your only responsibility will be report writing, until you can pay back Sam for his consulting fee analyzing the packet capture data."

"Ohh, man!"


And now for the winners…

Technical Winner is Brian Hart. See his entry HERE.

Creative Winner is Tim Medin. His submission is HERE.

And our Random Winner is Jacob Williams.

All three winners will receive signed copies of Ed Skoudis’ book, Counter Hack Reloaded. Congrats and keep up the good work.


Special thanks to all those who participated in the Brady Bunch Boondoggle (and who read this far to the end of the Boondoggle Redux).  I hope you enjoyed working on this challenge as much as I enjoyed writing it.  Please send me a post in the forum with any comments, questions or suggestions, or you can reach me at jwright *at* willhackforsushi.com.  -Josh

Category: Skillz

Comments are closed.