1. Extracting and Diffing Windows Patches in 2020

    It's been a while since I've posted anything here! After all, what are personal blogs for but ignoring for years at a time ;)
    Anyhow, I've been running through this demo when teaching SANS SEC760 and I thought I'd write it up so that researchers can come back to it later when they need it. It's also useful to document all of this stuff in one place, since the information about it seems scattered throughout the internet, as many Windows topics are.

    So why should you care about extracting and analyzing Windows patches? Doesn't the patch mean the bugs being fixed are now useless?


    Check out the full post for more details!
  2. Autoruns Bypasses

    Autoruns is a tool that is part of the Microsoft Sysinternals suite. It comes in permutations of console/GUI and 32/64 bit versions. Its main purpose is to detect programs, scripts, and other items that run either periodically or at login. It's a fantastic tool for blue teams to find persistent execution, but it is not perfect! By default, autoruns hides entries that are considered "Windows" entries (Options menu -> Hide Windows Entries). There is a checkbox to unhide them, but it introduces a lot of noise. In my preparations to red team for the Information Security Talent Search (ISTS) at RIT and the Mid-Atlantic Collegiate Cyber Defense Comptition (MACCDC) this year I found a few ways to hide myself among the Windows entries reported in Autoruns.

    For some prior work done in this area check out Huntress Labs's research and Conscious Hacker's research.


    Check out the full post for more details!
  3. Uberconference Hidden Hangup Button

    I was on an uberconference call the other day and the leader of the conference mentioned how they had the ability to disconnect anyone on the call with a "Hangup" button next to the mute and profile buttons. Looking at the interface a caller with the icons expanded looks like this:

    caller interface

    Now let's inspect... Going down to where the profile and mute buttons are located it looks like there's one more, hidden button available:

    hangup hidden html

    Removing the style="display: none;" attribute from the div causes the button to show...

    hangup enabled

    It's funny because it actually works. If you click it the person gets booted from the call, even if you aren't an admin/call leader. Web is hard.
    Thanks for reading.

  4. Hack Fortress 2019 - helloworld2.apk

    Final Score

    Another great year of Hack Fortress at Shmoocon!
    I wanted to do a post on this challenge in particular becuase it was one of two 300 point challenges on the board. I always get inside my own head about these challenges but I remind myself: they are not normal CTF challenges. These challenges are meant to be solved in just a few minutes, since the board is pretty big and the length of the competition is pretty short (30 min for prelims, 45 min for finals).

    I always focus on the Data Exploitation challenges because they usually have high point values and consist of android application reversing, basic binary reversing, macOS and image forensics (thanks Sarah), obscure encoding, crypto (sometimes), and hardware, among other things. It's a very diverse but fun category. I solved three challenges totalling 525 points in this category in the finals. This particular challenge was the majority of those points, but actually took the least time since I've had experience with android application reverse engineering before.

    The challenge details were:

    Name: HelloWorld2
    Location: helloworld2.apk
    Points: 300
    Desc: Find the encryption key

    Whenever I get an APK I do two things:

    Unfortunately my version of dex2jar was out of date so I had some issues with my automated decompilation tools. I ended up downloading the newest version of dextools, running dex2jar, loading the jar into JD-GUI, and exporting the sources.
    Android apps always start with MainActivity, which was in the class path fortress/hack/helloworld2. The decompiled code is below.

    package fortress.hack.helloworld2;
    import android.os.Bundle;
    import android.util.Base64;
    import android.view.View;
    import android.widget.EditText;
    import javax.crypto.Cipher;
    import javax.crypto.spec.IvParameterSpec;
    import javax.crypto.spec.SecretKeySpec;
    public class MainActivity
      extends AppCompatActivity
      public static String encrypt(String paramString1, String paramString2, String paramString3)
          IvParameterSpec localIvParameterSpec = new javax/crypto/spec/IvParameterSpec;
          paramString2 = new javax/crypto/spec/SecretKeySpec;
          paramString2.(paramString1.getBytes("UTF-8"), "AES");
          paramString1 = Cipher.getInstance("AES/CBC/PKCS5PADDING");
          paramString1.init(1, paramString2, localIvParameterSpec);
          paramString1 = Base64.encodeToString(paramString1.doFinal(paramString3.getBytes()), 0);
          return paramString1;
        catch (Exception paramString1)
        return null;
      public void enceyptData(View paramView)
        paramView = (EditText)findViewById(2131165238);
        ((EditText)findViewById(2131165239)).setText(encrypt(keyFromJNI(), getString(2131427370), paramView.getText().toString()));
      public native String keyFromJNI();
      protected void onCreate(Bundle paramBundle)

    We are looking for the encryption key. In the encrypt function the first paramter passed is the key. We know this because the first parameter to the init function of javax.crypto.spec.SecretKeySpec is the key as bytes. Encrypt is called from MainActivity.enceyptData (sic) and the first parameter is keyFromJNI(). The function keyFromJNI has the prototype public native String keyFromJNI(); which means that there is a native library in the application that will provide the key back to the java app.
    Native libraries for an android application can be found in the lib directory of the APK. The unpacked apk shows four different architectures in the lib directory: arm64-v8a, armeabi-v7a, x86, and x86_64. I chose to look at the x86 version of, since Hopper is better at x86 than other architectures (in my opinion).
    Since I have reverse engineered java native libraries before I know to look for the function name and/or class name in the function list. Pictured below is both the search and the decompiled function.


    Looks like the classic "build a string as integers" trick. I'm assuming sub_61a0 is some kind of memory allocation function, and arg0 is always the JNIEnv pointer, which contains a bunch of useful functions to convert C types into java types to return. I'm guessing the arg0+0x29c is either NewString or NewStringUTF. Moving forward I just took all of the hex bytes from the four integers that get put into the key buffer and unhexlified them.

    In [26]: from binascii import unhexlify as unhex
    In [27]: unhex("212b2b636f74746f47756f596563694e")
    Out[27]: b'!++cottoGuoYeciN'

    Looks promising, but backwards...

    In [28]: unhex("212b2b636f74746f47756f596563694e")[::-1]
    Out[28]: b'NiceYouGottoc++!

    And there's the flag!

  5. sqlalchemy Magic

    I was writing a plugin for CTFd and I was faced with an interesting problem: how the hell do I add a column (attribue) to a parent table without modifying that table (or model object)???
    I was trying to assign an extra attribute to the Teams model; a one-to-many relationship between bracket and team so I could have Teams.chal_bracket and Bracket.teams, but again without modifying the Teams model.
    I had actually tried overriding the Teams model and also adding a row on the fly, but neither of those worked. I ended up with the solution below: ...

    Check out the full post for more details!
  6. Server Side Google Analytics

    I stitched together a bunch of posts from different sites to get a working setup for server-side google analytics with unique user tracking. This allows you to have a completely static (javascript-free) site and still get useful analytics data.

    server {
        # all of your other config...
            userid         on;
            userid_name    uid;
            userid_domain  <<the domain you are using this on>>;
            userid_path    /;
            userid_expires 365d;
            userid_p3p     'policyref="/w3c/p3p.xml", CP="CUR ADM OUR NOR STA NID"';
            location / {
                    try_files $uri $uri/;
                    index index.html;
                    post_action @analytics;
            location @analytics {
                    set $ipaddr $remote_addr;
                    resolver ipv6=off;
                    proxy_pass<<your analytics UA- tag>>&cid=$uid_got&t=pageview&dh=$host&dp=$uri&dr=$http_referer&uip=$remote_addr;

    Of course replace the <<the domain you are using this on>> and <<your analytics UA- tag>> with the appropriate data.
    This will result in the server sending out a GET request with the client's info to the tracking URL for each page visit. It increases bandwidth used by your server but is a neat trick regardless.

  7. Upgrading an Amazon EC2 Instance from Ubuntu Trusty to Xenial

    I had a bad time.
    I ran a do-release-upgrade on one of my Amazon EC2 instances to try and upgrade it from 14.04 (Trusty) to 16.04 (Xenial). After the update and a reboot the box refused to come back up. When I detached the drive and attached it to another to check syslog I found this:

    /sbin/dhclient -1 -v -pf /run/ -lf /var/lib/dhcp/dhclient.eth0.leases -I -df /var/lib/dhcp/dhclient6.eth0.leases eth0
    Usage: dhclient [-4|-6] [-SNTP1dvrx] [-nw] [-p <port>] [-D LL|LLT]
                 [-s server-addr] [-cf config-file] [-lf lease-file]
                 [-pf pid-file] [--no-pid] [-e VAR=val]
                 [-sf script-file] [interface]
    Failed to bring up eth0.

    Oh good, it forgot how to eth0.
    I spent about four hours figuring out how to fix it:

    apt update
    apt -y upgrade
    cat  << EOF > /etc/update-manager/release-upgrades.d/unauth.cfg
    apt install -y network-manager
    apt update
    apt -y upgrade
    systemctl enable systemd-networkd
    systemctl enable systemd-resolved
    dpkg-reconfigure resolvconf
    apt-get -y autoremove
    rm /etc/update-manager/release-upgrades.d/unauth.cfg
    1. Make sure you are up to date first.
    2. Some packages (python3) complain that they are unauthenticated. Feel free to skip this if you want.
    3. Install the network-manager
    4. Leap of faith... do the upgrade
    5. Finish the upgrade by installing the rest of the packages.
    6. Enable the systemd network daemon and resolver daemon
    7. Reconfigure resolvconf so you can dns
    8. Get rid of the unauth.cfg file you created
    9. Reboot and pray.

    Thanks to these three links for the solutions (I just put them together):

  8. Scheduling Callbacks with WMI in C++

    I am going to be starting a series of posts on what I have learned on Windows pentesting and post exploitation. These posts will have a heavy focus on red teaming for competitions and cyber exercises. I am not a pentester, but I think some of the places to hide in Windows are cool so I want to write about them. These posts will include code snippets in powershell and C++. Much of this code I had to figure out how to write using the MSDN docs alone and feel that it is useful to put on the internet somewhere so others don't have to go through so much hassle to make it work.

    The topic of this post is scheduling persistent callbacks with Windows Management Instrumentation (WMI).

    WMI Explained (in brief)

    Essentially, WMI is an interface for configuration and information gathering on Windows systems. It is installed by default on Windows ME and up, which makes it a valuable resource for sysadmins and attackers. It contains information about all aspects of the system including processes, attached devices, and (I'm not kidding) games registered with Windows (wmic /namespace:\\root\cimv2\applications\games PATH game get). There is a lot of information here which will not be covered in this post. Exploration of what more WMI has to offer is left as an exercise to the reader!

    The interface consists of namespaces, classes, and instances of classes. Namespaces contain different classes and instances are instances of classes in a namespace. Think of a namespace as a database, a class as a table schema, and an instance as a row in that table. Instances can have properties and callable methods. One of the standard examples of method calling in WMI is creating a process with the WMI command line interface command wmic:

    wmic process call create calc.exe

    The above line will spawn calc.exe as the current user. ...

    Check out the full post for more details!
  9. A Better Way to Work with Raw Data Types in Python

    Working with raw data in any language can be a pain. If you are a developer there are many solutions to make it easier such as Google's Protocol Buffers. If you are a reverse engineer these methods can be too bulky especially if you are trying to quickly script an exploit (perhaps in a CTF where time is constrained). Python has always been my go-to language for exploit dev and general script writing but working with raw datatypes using just pack and unpack from the struct module is annoying and leaves much to be desired. I'm here to tell you that if you are still using pack and unpack for complex datatypes there is a better way.

    For the sake of this post we will attempt to work with the raw datatypes below defined as a C structures:

    typedef struct __attribute__((packed)) NestedStruct_ {
        unsigned char flags[3];
        uint8_t val1;
        uint8_t val2;
    } NestedStruct;
    typedef struct __attribute__((packed)) ExampleNetworkPacket_ {
        uint16_t version;
        uint16_t reserved;
        uint32_t sanity;
        NestedStruct ns;
        uint32_t datalen;
        unsigned char data[0];
    } ExampleNetworkPacket;

    The total size of the ExampleNetworkPacket structure will be 17 bytes plus any data appended on it.

    As a side note I just recently learned that the last element of the ExampleNetworkPacket is valid C and is useful to be a pointer to the end of the structure instead of having to do this:

    unsigned char data = (unsigned char*)(examplenetworkpacketptr + sizeof(ExampleNetworkPacket));


    Check out the full post for more details!
  10. Python for Hackers

    This is getting posted a bit late, but here is a presentation I gave remote for RIT's Competitive Cybersecurity Club Conference (RC4) 2016 on python tricks for hackers. It's a collection of things that I often use within python that make writing functional tools easier.