IsDebuggerPresent Bypass

There are many ways to do it. Here is a tutorial, how to get around IsDebuggerPresent, by simply patching this function so it always returns 0.

1) locate IsDebuggerPresent

In my situation, it is at 7664EFF7, and consist of only three instructions + one RET. It reads the thread block (address is at FS:18), and then locates the byte that says “i am being debugged” and returns it. The returns value is stored in EAX (as for most WINAPI functions). If I modify the function so that at the end it will have EAX = 0, I will have successfully bypassed IsDebuggerPresent.

2) patch it

Note that I also filled the rest of the function with NOPs to avoid changing the size of it. It probably is not necessary, you could also just do MOV EAX, 0 and then just RETN.

Also you should know, that the modification is only valid for one run of the program. When you restart it, it will load a new copy of kernel32.dll (where IsDebuggerPresent is located) with the original function, and you will have to apply the patch again. If you want to make the patch permanent, you need to modify the launching binary and modify/remove the call to this function. But before you do that you also need to make sure that the binary doesn’t check itself for modifications.

Another options:

Runtime patching:

  • Set EAX to zero after IsDebuggerPresent being called
  • Modify the PEB itself by injecting this code:
    mov eax,dword ptr fs:[18]
    mov eax,dword ptr ds:[eax+30]
    mov byte ptr ds:[eax+2],0

    This will patch the BeingDebugged flag in the PEB, ensuring IsDebuggerPresent always returns 0.

  • You can use a plugin like idastealth

Permanent Patching:

  • You can fill the call to IsDebuggerPresent with NOPs or something similar to skip the check


USB Device Status Change Tool

Automatically recognize and print PnP for USB devices, and select a specific device from the list and double-click on the device to force the device to stop. Double-clicking a device is a tool that can be changed again.

It’s a tool that came to save you, trying to get rid of all USB devices that bother. = _ =;

Download deviceinfo_cs_ver full source code

const int DIGCF_PRESENT = 0x2;
const int DIGCF_ALLCLASSES = 0x4;
const int SPDRP_DEVICEDESC = 0x0;
const int SPDRP_CLASS = 0x7;
const int CR_SUCCESS = 0x0;
const int DN_STARTED = 0x8;
const int CM_PROB_DISABLED = 0x16;
public uint cbSize;
public Guid classGuid;
public IntPtr devInst;
public ulong reserved;
[DllImport("setupapi.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto, SetLastError = true)]
static extern IntPtr SetupDiGetClassDevs(
IntPtr classGuid,
[MarshalAs(UnmanagedType.LPTStr)] string enumerator,
IntPtr parentWindow,
uint flags
[DllImport("setupapi.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto, SetLastError = true)]
static extern IntPtr SetupDiDestroyDeviceInfoList(
IntPtr devInfo
[DllImport("setupapi.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto, SetLastError = true)]
static extern Boolean SetupDiEnumDeviceInfo(
IntPtr deviceInfoSet,
int memberIndex,
ref SP_DEVINFO_DATA deviceInfoData
[DllImport("setupapi.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto, SetLastError = true)]
static extern bool SetupDiGetDeviceRegistryProperty(
IntPtr deviceInfoSet,
ref SP_DEVINFO_DATA deviceInfoData,
uint property,
out UInt32 propertyRegDataType,
IntPtr propertyBuffer,
uint propertyBufferSize,
out UInt32 requiredSize
[DllImport("setupapi.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto, SetLastError = true)]
static extern int CM_Get_DevNode_Status(
ref UInt32 status,
ref UInt32 probNum,
IntPtr devInst,
int flags
public Form1()
private void button1_Click(object sender, EventArgs e)
if (this.textBox1.Text.Length == 0)
string enumerator = this.textBox1.Text;
IntPtr devInfo = SetupDiGetClassDevs(IntPtr.Zero, enumerator, IntPtr.Zero, DIGCF_PRESENT | DIGCF_ALLCLASSES);
if (devInfo.ToInt32() == -1)
for (int index = 0; ; ++index)
devInfoData.devInst = (IntPtr)0;
devInfoData.classGuid = Guid.Empty;
devInfoData.reserved = 0;
devInfoData.cbSize = 28; // x86에서는 28바이트입니다. //  x86, click 28.
if (SetupDiEnumDeviceInfo(devInfo, index, ref devInfoData) == false)
UInt32 regType = 0;
uint requiredSize = 0;
uint size = 256;
IntPtr classNameBuffer = new IntPtr();
classNameBuffer = Marshal.AllocHGlobal((int)size);
SetupDiGetDeviceRegistryProperty(devInfo, ref devInfoData, SPDRP_CLASS, out regType, classNameBuffer, size, out requiredSize);
string className = Marshal.PtrToStringAuto(classNameBuffer);
IntPtr descriptionBuffer = new IntPtr();
descriptionBuffer = Marshal.AllocHGlobal((int)size);
SetupDiGetDeviceRegistryProperty(devInfo, ref devInfoData, SPDRP_DEVICEDESC, out regType, descriptionBuffer, size, out requiredSize);
string description = Marshal.PtrToStringAuto(descriptionBuffer);
string statusString = "";
UInt32 status = 0, probNum = 0;
int ret = CM_Get_DevNode_Status(ref status, ref probNum, devInfoData.devInst, 0);
if (ret == CR_SUCCESS)
if ((status & DN_STARTED) == DN_STARTED)
statusString = "사용 / Use";
if (probNum == CM_PROB_DISABLED)
statusString = "사용 안함 / Disable";
statusString = "문제 코드 / Problem code: " + probNum.ToString();
statusString = "상태 조회 실패 / Health check failed";
var itemArray = new String[] { className, description, statusString };
this.listView1.Items.Add(new ListViewItem(itemArray));

Please excuse me if the source is messy/ Sorry for bad english.

Well, thanks!

ARM Mode and the Thumb Mode classification – Android


Now I’m going to step into the world of Android ARM.

First of all

About ARM and Thumb Mode
ARM and Thumb are two different instruction sets supported by ARM cores with a “T” in their
name. For instance, ARM7 TDMI supports Thumb mode. ARM instructions are 32 bits wide, and
Thumb instructions are 16 wide. Thumb mode allows for code to be smaller, and can potentially be
faster if the target has slow memory.

Now that you’re familiar with this, you know, some of the first things that you need, but let’s take a look at what you need.

Let’s take a quick look at the ARM Mode and Thumb Mode.

On the ARM CPU, you can think of code execution as the meaning of how to interpret the code (how to interpret the code).It is divided into ARM Mode and Thumb Mode.

For ARM Mode, the anthropoments always use 32 bits.

For Thumb Mode, interpret the default 16 bits.

But this Thumb Mode is a bit more troubling.

As you can see, it’s more like a couple of times, but in the case of Thumb Mode, it’s 16 bits per bit, and it’s 32 bits.

So how would you categorize the code to be executed in the ARM Mode stamp mode?

It’s very simple.

As you know, the memory address loaded to run is stored in the PC (Program Counter).

If 0 0 bits of this address are 0, the ARM Mode is ARM Mode, and then the Thumb Mode is the Thumb mode.

And the CPU is written to bits 5 of the CPSR register that plays this information similar to the EFLAGS of Intel x86. If you are in theox mode, set the set to 1.

Then, let’s check the function of the function in the ARM Mode journal Thumb Mode journal.

For the first time, we’ll take the following code and debug it to the Android studio.

(Testing environment was conducted in an environment of Android marshmallow ARMv7.)

Our function, DebugTest() and fopen(), respectively, will look at the brake point of each mode and look at the brake point.

Let’s start by looking at what mode the current code is running.

Read the CPSR register to read 0x600F.

I need to look at bit 5, so binary changes …

Bit 5 is 1! Running in Thumb Mode.

And let’s look at the DebugTest() function, which was saved in this_function() function, in 0xEE831F8D

Bit zero! It is Thumb Mode again! D : D

Here’s to you again!

And then we’ll look at it in detail, but in the diagram, the actual code is in alignment, and in fact, the execution is in alignment.

Something’s wrong with the assembly code?

So let’s clean up. Let’s explore the code of 0xEE831F8C.

Now the code is good!^^

It is important to refer to the code address again later, but it is very important to address the code address.

Let’s debug this code to IDA as an IDA and test the actual file.

That’s it.

Today we briefly found out about the ARM Mode and the Thumb Mode classification.

Next time we will learn about encoding.

Thanks and sorry for bad english :D.

Understanding/Detecting Inline Hooks/ WinAPI Hooks (Ring3)

Ever wonder how malware is able to harvest credentials from within web browsers? The most popular method is a Man-in-The-Browser (MiTB) attack known as inline hooking (sometimes referred to as detours). Inline hooks are incredibly versatile and very common in malware. With inline hooks, malware can become puppetmaster of any process, manipulating it into doing whatever the malware author pleases. Let’s see how they do it.


How do you get your code into the target process?

The first step in inline hooking is to get your code to run inside the target process. This process is known as injection.

There are several common injection methods that we see in the wild. For our example, we use VirtualAllocEx to create a memory region inside of Firefox at 0x0D000000CreateRemoteThread would then be used to begin execution inside of Firefox in the 0x0D000000 region in order to set the hooks and to take care of initialization. (The actual injection process is an intricate topic on its own and is outside the scope of this post.) Here is what our injected code block looks like. The highlighted areas will become clearer as we go on.

There are four parts to the inline hook: the hook, the malicious code (which is filled with NOPs here), the execution of trampled bytes, and the return.

What is a Windows API?

It’s a set of functions and data structures that a Windows program can use to ask Windows to do something, like opening a file, displaying a message, etc.

Pretty much everything that a Windows program does involves calling various API functions.

Collectively, all the API functions that Windows makes available are called “The Windows API”.

The hook

The hook, sometimes referred to as the trampoline, is analogous to a traffic officer redirecting traffic to another location. For our example, we will be hooking the send() function from the ws2_32 library. Below is a picture of the first few instructions in the ws2_32!send function as it appears normally. In order to place the hook, we need to overwrite some existing instructions in the function. The green box highlights the bytes that we will overwrite.

Notice that five bytes are going to be overwritten. This is the exact number of bytes needed for our hook: a jmp instruction that jumps into our code at 0x0D000000. (There are other ways to place the hook such as with a push addr, ret instruction combination.) Here is the same send() function after the hook is placed:

The malicious code

Now that execution flow has been redirected to our injected code, registers must be saved to ensure that we do not crash when we return execution to the send()function. In 32-bit processes, we can save all of the registers with the pusha instruction. When the malicious code is finished executing, the popad instruction will restore all the registers to the state they were in when the send() call was initially executed. Now that we are in control of the send() function, we must come up with something interesting to do. One thing we could do is to look and see if a POST request is being sent and send that data back to our command and control in hopes it will contain login credentials.


The execution of trampled bytes and the return

After we have done something useful with our malicious code, we have to make sure our process returns to the exact same state it was in before our hook took over. First, we use the popad instruction to restore all of our registers. Remember those five bytes we trampled over when we set the hook? Those original instructions still need to be run, so they were copied to the end of the malicious code during the hooking process so that they seamlessly run after the registers are restored. Lastly, we jump home safely into the send function + 0x05 (the length of our hook).

Putting it all together

Let’s take one more look at everything we did to get the full picture. Follow the arrows to see the flow of execution for a normal, unhooked send() function in Firefox:

After injecting our detour, the flow of execution now looks like this:

Reasons for hooking API calls

You can probably think of a reason to hook every API call imaginable. Here are a few:

  • urlmon!URLDownloadToFile – Used to intercept downloaded files. Shifu hooks this function in every process in order to prevent new malware from downloading.
  • ws2_32!send – Used to capture POST credentials from unencrypted traffic.
  • GetHostByName – Shifu hooks this function in order to ignore traffic to its command and control sites.
  • ws2_32!recv – Used to capture incoming packet data from unencrypted traffic.
  • Advapi32!CryptEncrypt – Used for capturing data before it gets encrypted because it won’t be plain text when it goes out the send() function.
  • Advapi32!CryptDecrypt – Used to decrypt encrypted data coming in from the recv() function.
  • User32!GetMessage – Shifu uses a hook here to intercept mouse click messages in order to take pictures of virtual keyboard clicks.
  • Kernel32!ExitProcess– Useful to prevent process from closing itself (bypassing game anticheats)


Here is a pseudocode of a simple solution, but not very effective if the attacker is a harduser. This following code will check if the prologue of api ExitProcess starts with 0xE9 (opcode JMP)

FARPROC Address = GetProcAddress(GetModuleHandle("kernel32.dll"),"ExitProcess");
if (*(BYTE*)Address == 0xE9)
 printf("Api hooked\n");//Do your thing


Ring3 / Ring0 Rootkit Hook Detection Part 2

Part 1

If you haven’t read part 1 of this article, here it is:

IAT Hooks

The Import Address Table (IAT) is a table of jumps “jmp dword ptr ds:[address]”. Because functions in dlls change address, instead of calling a dll function directly, the application will make a call to the relevant jmp in its own jump table. When the application is executed the loader will place a pointer to each required dll function at the appropriate address in the IAT.
if a rootkit were to inject itself inside the application and modify the addresses in the IAT, it would be able to receive control every time a target function is called.
Because the Export Address Table (EAT) of each dll remains intact, an application could easily bypass IAT hooks by just calling GetProcAddress to get the real address of each dll function. In order to prevent such a simple bypass, a rootkit would likely hook GetProcAddress/LdrGetProcedureAddress and use it to return fake addresses. These hooks can be bypassed by writing your own GetProcAddress implementation and using it to get the real function addresses.

Inline Hooks

Inline hooking is a method of receiving control when a function is called, but before the function has done its job. The flow of execution is redirected by modifying the first few (usually 5) bytes of a target function. A standard way to do this is to overwrite the first 5 bytes of the function with a jump to malicious code, the malicious code can then read the function arguments and do whatever it needs. If the malicious code requires results from the original function (the one it hooked): it may call the function by executing the 5 bytes that were overwritten then jump 5 bytes into the original function, which will miss the malicious jump/call to avoid infinite recursion/redirection.

Bypass / Detection (Ring 3)

In usermode inline hooks are usually place inside functions that are exported by a dll. The most accurate way to detect and bypass these hooks would be to compare each dll against the original code. First a program would need to get a list of each dll that is loaded, find the original file and read it, align and load the sections into memory then perform base relocation. Once the new copy of the dll is loaded into memory, the application can walk the export address table and compare each function vs that in the original dll. In order to bypass hooks, an application can then either replace the overwritten code using the code from the newly loaded dll, alternatively, it could resolve imports in the newly loaded dll and use it instead (be aware that some dlls will not work if more than 1 instance is loaded).
This method of bypassing dll hooks practically involves writing your own implementation of LoadLibrary, it’s really not for the beginners or faint-hearted. As much as I would like to post the code to do this, I won’t, because it can (and will) be used by scriptkiddies to bypass usermode antivirus sandboxes or fight with other rootkits.
(We can also use manual dll loading to detect / fix EAT hooks, I won’t go into this in detail as EAT hooks are very uncommon).
Bypass / Detection (Ring 0)
In kernel mode, inter-modular jumps are a lot more rare. Hooks in ntoskrnl can usually be detected by disassembling each instruction in each function, then looking for jumps or calls that point outside of ntoskrnl (into driver bodies, etc). It is also possible to use the same method explained for usermode hook detection: a driver could read each ntoskrnl module from disk, load it into memory and compare the instructions against the original.
For inline hooks within drivers, scanning for jmp / call instructions that point outside of the driver body is much more likely to result in false positives, however, non-standard drivers that are the target of jumps / calls inside standard kernel drivers should raise a red flag. It is also possible to read drivers from disk. As drivers generally do not export many functions and IRP major function pointers are only initialized at runtime, it would probably be required that you compare the entire code section of the original and new driver. It is important to note that relative calls / jumps are susceptible to changes during relocation, this means that there will naturally be some differences between the original and new driver, however both relative calls / jumps should point to the same place.

SSDT Hooks

The System Serivce Dispatch Table (SSDT) is a table of pointers for various Zw/Nt functions, that are callable from usermode.  A malicious application can replace pointers in the SSDT with pointers to its own code.

Detection (Ring 0)
All pointers in the SSDT should point to code within ntoskrnl, if any pointer is pointing outside of ntsokrnl it is likely hooked. It’s possible a rootkit could modify ntoskrnl.exe (or one of the related modules) in memory and slip some code into an empty space, in which case the pointer would still point to within ntoskrnl. As far as I’m aware, functions starting with “Zw” are intercepted by SSDT hooks, but those beginning with “Nt” are not, therefore an application should be able to detect SSDT hooks by comparing Nt* function addresses with the equivalent pointer in the SSDT.

A simple way to bypass SSDT hooks would be by calling only Nt* functions instead of the Zw* equivalent. It is also possible to find the original SSDT by loading ntoskrnl.exe (this can be done easily with LoadLibraryEx in usermode) then finding the export “KeServiceDescriptorTable” and using it to calculate the offset of KiServiceTable within the disk image (Usermode applications can use NtQuerySystemInformation to get the kernel base address) , a kernel driver is required to replace the SSDT.


SYSENTER_EIP points to the code to be executed when the SYSENTER instruction is used. Usermode applications use SYSENTER to transition into kernel mode and call a kernel function (Those beginning with Nt/Zw), usually it would point to KiFastCallEntry, but can be replaced in order to hook all usermode calls to kernel functions.Detection / Bypass
SYSENTER_EIP hooking does not effect kernel mode drivers, and cannot be bypassed from usermode. In order to allow usermode applications to bypass this hook, a kernel driver must set SYSENTER_EIP to its original value (KiFastCallEntry), this can be done using the WRMSR instruction, however because KiFastCallEntry is not exported by ntoskrnl, getting the address could be tricky.

IRP Major Function Hook

The driver object of each driver contains a table of 28 function pointer, these pointer are to be called by other drivers via IoCallDriver or alternative means, the pointers correspond to operations such as read/write (IRP_MJ_READ/IRP_MJ_WRITE). These pointers can easily be replace by another driver.Detection
Generally all IRP major function pointers for a driver should point to code within the driver’s address space, this is not always the case, but is a good start to identifying malicious drivers which have redirected the IRP major functions of legitimate drivers to their own code.

Due to IRP major function pointers being initialized from withing the driver entry point (during runtime), it’s not really possible to get the original values by reading the original driver from disk, there are also issues with loading a new copy of the driver due to collisions. The only way I can think of for bypassing these sorts of hooks would be calling the lower driver (Drivers are generally stacked and the top driver passes the data to the driver below and so on, if the lowest driver isn’t hooked, an application could just send the request directly to the lowest driver).


There are many ways to hook, so it’s hard to avoid all of them.
Part 3 soon.

Ring3 / Ring0 Rootkit Hook Detection Part 1


The cybercrime underworld hasn’t given me any exciting malware to reverse and I’m running out of ideas for new posts, so I’m going to do a 2 part article about the techniques used by rootkits to intercept function calls, and how to detect them. The first part will explain some hooking methods, the second part will explain how to detect them. As I haven’t done any kernel mode stuff on this blog, I will be looking at both user mode and kernel mode hooks on a x86 windows system.

Execution Flow

In order to get a better understanding of the attack surface, I’ve made a simplified flow chart of a call to the WriteFile function in kernel32.dll. This is just an example to highlight key points, I chose the WriteFile function as it makes for a nice example, and disk I/O is commonly intercepted by malware, however most of the stuff on this graph will apply to lots of functions.
  • WriteFile is just a simple wrapper for NtWriteFile.
  • Can be hooked with inline, IAT or EAT hooks.
  • Hooking this function will intercept all calls to WriteFile in whichever process the hooks are placed.
  • All paths used inside kernel32 are generally Dos Paths (C:file.txt).


  • NtWriteFile is a small stub that sets the EAX register to a 32bit value (I’ll explain this value later), then calls KiFastSystemCall.
  • Can be hooked with inline, IAT, or EAT hooks.
  • Hooking this function will intercept all calls to CreateFile, NtWriteFile or ZwWriteFile in whichever process the hooks are placed.
  • All paths used by ntdll file functions are generally NT Paths (??C:file.txt).
  • In order to call KiFastSystemCall NtWriteFile moves the address 0x7FFE0300 (KiFastSystemCall / KiFastSystemCall Pointer) into the EDX register, then it does “call edx” or “call dword ptr [edx]”
  • The rootkit could replace the address 0x7FFE0300 within the NtWriteFile function body in order to hook it.
  • Hooking this function will intercept all calls to CreateFile, NtWriteFile or ZwWriteFile in whichever process the hooks are placed.
  • All paths used by ntdll file functions are generally NT Paths (??C:file.txt).

  • KiFastSystemCall is a small stub that moves the stack pointer into the EDX register then executes the sysenter.
  • The stub is only 5 bytes in size and the last instruction (RETN) is pointed to by KiFastSystemCallRet, this only leaves 4 writable bytes (not enough space for a near call/jmp). Furthermore, the address is hard-coded which makes IAT or EAT hooks impossible.
  • Sometimes the KiFastSystemCall stub resides in KUSER_SHARED_DATA, in which case it is not writable from usermode.
  • By hooking this function, the rootkit gains the ability to intercept all user mode calls to kernel functions.

  • The SYSENTER instruction is what transfers execution from user mode to kernel mode, in order to execute an kernel function. when the instruction is executed, the CPU sets the code segment to the content  of the SYSENTER_CS register, the stack pointer to the content of the SYSENTER_ESP register, and the EIP to the content of the SYSENTER_EIP register. The SYSENTER_EIP register points to the KiFastCallEntry function ntoskrnl, as a result of this, the cpu will begin executing KiFastCallEntry.
  • These registers are known as MSRs (Model Specific Register), they are only readable by using the cpu instruction RDMSR (Read MSR) and writable using the WRMSR (Write MSR) instruction. These instructions are both privileged (can only be executed from ring 0) therefore, in order to hook, a kernel driver must be loaded.
  • By modifying the SYSENTER_EIP, the rootkit gains the ability to intercept all user mode calls to kernel functions, but we cannot intercept any kernel mode calls, because only user mode call use SYENTER.

  • KiFastCallEntry is responsible for taking the 32bit value from the EAX register (this is the value we mentioned in 2). The first 11 bits are the ordinal of the SSDT function to use (SSDT_Address+(Ordinal*4)), the 12th and 13th byte determine which SSDT to use, the rest of the bits are ignored. Once the function has worked out which SSDT to use, it calls the address at the given ordinal in the table.
  • Can be hooked with an inline hooks.
  • By hooking this function, the rootkit can intercept all user mode calls to kernel functions, as well as all kernel mode calls to functions starting with Zw, but not those starting with Nt.
  • Because the SSDT is a table of function pointers, it is also possible to hook calls by replacing the pointer within the SSDT. For every kernel function in ntdll, there is an equivalent pointer within the SSDT, therefore we can hook any function at will just by replacing the pointer. We are also able to hook all kernel mode calls to functions starting with Zw using this method, however, we cannot hook kernel mode calls to functions starting with Nt.

  • NtWriteFile…Again. We saw a call to NtWriteFile in 2, however that was just an ntdll.dll stub to enter into kernel mode, this is the actual NtWriteFile call pointed to by the address at the given SSDT ordinal.
  • NtWriteFile builds an IRP (I/O Request packet) and supplies it to IopSynchronousServiceTail, it also passes a device object associated with the file being written.
  • Can be hooked with an inline hook.
  • By hooking this function, the rootkit can intercept user mode and kernel mode calls to NtWriteFile and ZwWriteFile.

  • IopSynchronousServiceTail may only be used on certain versions of windows, it is just a simple wrapper for IofCallDriver, so I’ll skip this.

  • IofCallDriver takes a device object pointer (PDEVICE_OBJECT) and IRP pointer (PIRP) (both supplied by NtWriteFile). The device object contains a pointer to the driver object of the driver associated with that device (PDRIVER_OBJECT). The driver object contains a member called “MajorFunction”, this is an array of 28 driver defined function pointers (a bit like an EAT or the SSDT), ofCallDriver will call one of the IRP major functions, based on which one is specified by the “MajorFunction” member in the IO_STACK_LOCATION for the supplied IRP.In the case of file operations, the device object given by NtWriteFile will nearly always be filesystemntfs (aka ntfs.sys) or a filter device attached to FileSystemNtfs, because filter drivers pass on the call to the device below below them until it gets to FileSystemNtfs, we can assume the call will always end up at filesystemntfs unless one of the filter drivers cancels it. Here is a full list of IRP major function names:
    • By hooking IofCallDriver, the rootkit can intercept practically any call to any driver. In order to only intercept calls to a certain driver, the rootkit can check the “DriverName” member pointed to by the driver object which is pointed to by the device object. Alternatively to intercept calls to a certain device, the rootkit could call ObQueryNameString on the device object (It is important to note that not all devices have names). The rootkit can also filter only specific IRP major function calls, this is done by calling “IoGetCurrentIrpStackLocation” on the IRP pointer, then checking the “MajorFunction” member of the returned IO_STACK_LOCATION.

    • The IRP_MJ_WRITE function is responsible for writing files within the filesystem.
    • By attaching a filter device to the device stack of FileSystemNtfs or by replacing an IRP major function pointer with one of its own, the rootkit can intercept any call to FileSystemNtfs. In order to intercept NtWriteFile calls, the rootkit would need to inspect IRP_MJ_WRITE calls in the filter device, or replace the IRP_MJ_WRITE pointer in the driver object.

    • This refers to the volume and partition drivers that are used by FileSystemNtfs, these are not normally targeted by rootkits, therefore i have left them out.
    • These drivers can be hooked in the same way as 9.

    • The NTFS filesystem uses the IRP_MJ_WRITE major function of the class driver “DriverDisk” aka disk.sys, in order to write a disk. Because DriverDisk is much lower level than the NTFS filesystem driver, there are no file name, instead it is only possible to work with LBAs (Logical Block Addresses). Logical Block Addressing in a linear method of addressing the disk by sectors, each sector is usually 512, 1024, 2048, or 4096 bytes. The sector number starts at 0 (Master Boot Record) and goes up to whatever, depending on the size of the disk.
    • Hooking of drivers lower than ntfs.sys is usually only seen in kernel mode payload drivers used by bootkits. This is due to the fact that bootkits tend to only work with files outside of the NTFS filesystem, therefore not having to worry with translating file names to LBAs.

    • The disk subsystem refers to any driver(s) below disk.sys, generally this a port/miniport driver, which is a hardware or protocol specific driver. In most cases this will be atapi.sys or scsiport.sys which are for ATA and SCSI complaint disk devices.
    •  At this level a new IRP major function is used, IRP_MJ_SCSI, which is an alias for IRP_MJ_INTERNAL_DEVICE_CONTROL. Here, the rootkit will have to work with SCSI_REQUEST_BLOCK parameters, which further complicates things compared to a disk.sys hook.
    • Any port/miniport hooks are usually only found in advanced kernel mode payload drivers used by bootkits.

How to Install OpenVPN on CentOS VPS

OpenVPN is an open source virtual private network (VPN) software. Follow the steps below to configure OpenVPN on CentOS:

1. Install dependencies:

# yum install gcc make rpm-build autoconf.noarch zlib-devel pam-devel openssl-devel


2. Get OpenVPN:

# wget

# wget


3. Prepare to install:

# rpmbuild –rebuild lzo-1.08-4.rf.src.rpm

# rpm -Uvh /usr/src/redhat/RPMS/x86_64/lzo-*.rpm

# rpm -Uvh rpmforge-release-0.3.6-1.el5.rf.x86_64.rpm


4. Install OpenVPN:

# yum install openvpn


5. Copy the OpenVPN directory:

# cp -r /usr/share/doc/openvpn-2.2.0/easy-rsa/ /etc/openvpn/


6. Build SSL keys. When prompted for key information, you can simply press enter to bypass:

#cd /etc/openvpn/easy-rsa/2.0

#chmod 755 *

#source ./vars




#./build-key-server server



7. Create the OpenVPN config:

# cd /etc/openvpn

# vi server.conf


Copy the following sample config into the document, edit the IP address and port to your main IP address and desired port, then press ESC, then :wq and enter to save and exit the document.


local #- change it with your server ip address

port 1234 #- change the port you want

proto udp #- protocol can be tcp or udp

dev tun

tun-mtu 1500

tun-mtu-extra 32

mssfix 1450

ca /etc/openvpn/easy-rsa/2.0/keys/ca.crt

cert /etc/openvpn/easy-rsa/2.0/keys/server.crt

key /etc/openvpn/easy-rsa/2.0/keys/server.key

dh /etc/openvpn/easy-rsa/2.0/keys/dh1024.pem

plugin /usr/share/openvpn/plugin/lib/ /etc/pam.d/login




push “redirect-gateway def1”

push “dhcp-option DNS”

push “dhcp-option DNS”

keepalive 5 30




status server-tcp.log

verb 3


8. Start OpenVPN:

# openvpn /etc/openvpn/server.conf

Check that it returns “Initialization Sequence Completed.” If so, press ctrl-c to quit.


9. Setup NAT rules:

# echo 1 > /proc/sys/net/ipv4/ip_forward

# iptables -t nat -A POSTROUTING -s -j SNAT –to

(Modify “” to your server’s IP)


Create a user to login to the VPN with:

#useradd username -s /bin/false

#passwd username


10. Create an OpenVPN config file on your local machine with name vpn1.ovpn, copy the sample below with your IP and port, and place it in your OpenVPN configurations folder:


dev tun

proto udp

remote 4567 #- your OPENVPN server ip and port

resolv-retry infinite


tun-mtu 1500

tun-mtu-extra 32

mssfix 1450



ca ca.crt



verb 3


11. Download ca.crt from /etc/openvpn/easy-rsa/2.0/keys to the same OpenVPN configs folder.

12. Start the VPN on the VPS:

# openvpn /etc/openvpn/server.conf


Log in to the VPN from your local machine (using OpenVPN or another desktop client) with the username/password you created.

How to Install VNC w/ GNOME on Debian VPS

VNC is a remote desktop sharing system that will allow you to connect your home PC to a GUI (graphical interface) hosted on your VPS, for easy remote management. This guide will walk you through the steps required to setup and access a VNC server hosted on a Debian VPS.

Before beginning, ensure you are logged in to your VPS as the root user, and run the following:

# apt-get update # apt-get upgrade

  1. Install GNOME:

# apt-get install gnome-desktop-environment

  1. Install required fonts:

# apt-get install xfonts-100dpi # apt-get install xfonts-100dpi-transcoded# apt-get install xfonts-75dpi # apt-get install xfonts-75dpi-transcoded# apt-get install xfonts-base

  1. Install TightVNCServer:

# apt-get install tightvncserver

  1. Start TightVNCServer for the first time, it will copy config files and prompt you for a password:

# tightvncserver :1

  1. Stop the VNC server, so we can continue to configure it:

# tightvncserver -kill :1

  1. Edit the xstartup file:

# vi ~/.vnc/xstartup

Press “A” to enter edit mode. Replace the contents of the file with the following (or edit to match):

# !/bin/shxrdb $HOME/.Xresources xsetroot -solid greyx-terminal-emulator -geometry 80x24+10+10 -ls -title "$VNCDESKTOP Desktop" & # x-window-manager &gnome-session &

Press ESC, type :wq, then press enter to save and close the file.

  1. Start the VNC server with your desired resolution:

# tightvncserver -geometry 1024x768 :1

You can now access your server’s remote GNOME desktop with a desktop VNC client. Enter your server’s main IP address, Port 1 (or 5901, alternately), and the password you set earlier to connect to the desktop.

Installing php7.0-fpm With Nginx Web Server

Installing php7.0-fpm With Nginx has never been easier. Everything you need is provided by the package manager in most cases with just a few commands to install. First let’s take a look at the php FPM module and the Nginx web server.

What is Nginx?

Nginx is a high performance load balancer, web server, and reverse proxy. Nginx is the heart of the modern web and a big contender to Apache. Here at BitAccel we prefer nginx for general and advanced use over Apache due to it’s ease of use and robustness. In this article we will be using Nginx as our web server.

What is php7.0-fpm?

PHP7.0 is currently the latest and greatest version of PHP from the PHP project. PHP can be served up many different ways, and one of those ways is with the FPM(FastCGI Process Manager) module. PHP-FPM is an improvement over the PHP-CGI module because it includes adaptive process spawning among other neat features.

How does php7.0-fpm work?

When implementing this module think of PHP-FPM and/or PHP-CGI as their own web server like Apache or Nginx. PHP-FPM processes the PHP files and renders the output to a unix socket or tcp socket. This data can then be read directly from the socket by a web server and served over the web. PHP also has it’s own built in web server that can be initialized from the php command line but is only meant for testing purposes.

So how do I install nginx with php?

Let’s get down to the dirty part. We’ll assume you are using Debian or Ubuntu distributions for the upcoming commands. With this script we are also installing a mysql database service called mariadb and adding dotdeb to our repo. If you get any errors let us know in the comments and we’ll diagnose and update the article.

#add dotdeb to the sources.list
#You need to change 'jessie' here to whatever version of Debian you are running.
echo "deb jessie all" >> /etc/apt/sources.list
echo "deb-src jessie all" >> /etc/apt/sources.list
apt-key add dotdeb.gpg
#export so we dont get any whiptail dialogs asking for input
export DEBIAN_FRONTEND=noninteractive
apt-get -q -y update
apt-get -q -y install nginx-full
apt-get -q -y install mariadb-server-10.0 mariadb-client-10.0 mariadb-client-core-10.0 mariadb-server-core-10.0
apt-get -q -y install wget
#for ubuntu we need libturbo for php gd not in the repos
read -p "Are you running this on Ubuntu? " -n 1 -r
if [[ $REPLY =~ ^[Yy]$ ]]
if [wget -q ""] && [dpkg -i libjpeg62-turbo_1.5.1-1_amd64.deb]; then
else echo "Fatal error installing libjpeg62-turbo for the php7.0-gd library, not continuing."
return 0
apt-get -q -y install php7.0-fpm php7.0-cli php7.0-common php7.0-curl php7.0-dbg php7.0-gd php7.0-imap\
php7.0-json php7.0-ldap php7.0-mcrypt php7.0-mysql php7.0-odbc php7.0-opcache php7.0-pgsql php7.0-phpdbg\
php7.0-pspell php7.0-readline php7.0-recode php7.0-snmp php7.0-sqlite3 php7.0-sybase php7.0-tidy
#setup our default nginx server
cat > /etc/nginx/sites-enabled/default <
server { 
listen 80 default_server;
root /var/www/; 
server_name _; 
location / {
index index.php; 
location ~ \\.php$ {
fastcgi_split_path_info ^(.+\\.php)(/.+)$;
# NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
# With php7.0-fpm:
fastcgi_pass unix:/var/run/php/php7.0-fpm.sock; 
fastcgi_index index.php; 
include /etc/nginx/fastcgi_params; 
fastcgi_param SCRIPT_FILENAME /var/www/\$fastcgi_script_name;
#download adminer so we can manage our database if needed
wget -O /var/www/adminer.php
#start up our services
service php7.0-fpm restart
service nginx restart
service mysql restart

The above code can be ran as a bash script by saving this to a file such as ‘’ and running ‘sh’ from your terminal or you can execute each of these lines on their own by pasting them into your terminal.

Nginx and PHP-FPM are installed!

Now you can enjoy your installation by uploading php files in /var/www and visiting ‘localhost’ in your favorite web browser, or the ip address of the machine you’ve installed this on.

How to Install / Setup Linux, Apache, MySQL, PHP (LAMP) on Debian and Ubuntu

About LAMP

LAMP stack is a group of open source software used to get web servers up and running. The acronym stands for Linux, Apache, MySQL, and PHP. Since the virtual private server is already running Ubuntu, the linux part is taken care of. Here is how to install the rest.

Set Up

The steps in this tutorial require the user to have root privileges on your VPS. You can see how to set that up in the Initial Server Setup in steps 3 and 4.

Step 1: Install Apache

Apache is a free open source software which runs over 50% of the world’s web servers.

To install apache, open terminal and type in these commands:

sudo apt-get update
sudo apt-get install apache2

That’s it. To check if Apache is installed, direct your browser to your server’s IP address (eg. The page should display the words “It works!” like this.

How to Find your Server’s IP address

You can run the following command to reveal your server’s IP address.

ifconfig eth0 | grep inet | awk '{ print $2 }'

Step 2: Install MySQL

MySQL is a powerful database management system used for organizing and retrieving data

To install MySQL, open terminal and type in these commands:

sudo apt-get install mysql-server libapache2-mod-auth-mysql php5-mysql

During the installation, MySQL will ask you to set a root password. If you miss the chance to set the password while the program is installing, it is very easy to set the password later from within the MySQL shell.

Once you have installed MySQL, we should activate it with this command:

sudo mysql_install_db

Finish up by running the MySQL set up script:

sudo /usr/bin/mysql_secure_installation

The prompt will ask you for your current root password.

Type it in.

Enter current password for root (enter for none): 

OK, successfully used password, moving on...

Then the prompt will ask you if you want to change the root password. Go ahead and choose N and move on to the next steps.

It’s easiest just to say Yes to all the options. At the end, MySQL will reload and implement the new changes.

By default, a MySQL installation has an anonymous user, allowing anyone
to log into MySQL without having to have a user account created for
them.  This is intended only for testing, and to make the installation
go a bit smoother.  You should remove them before moving into a
production environment.

Remove anonymous users? [Y/n] y                                            
 ... Success!

Normally, root should only be allowed to connect from 'localhost'.  This
ensures that someone cannot guess at the root password from the network.

Disallow root login remotely? [Y/n] y
... Success!

By default, MySQL comes with a database named 'test' that anyone can
access.  This is also intended only for testing, and should be removed
before moving into a production environment.

Remove test database and access to it? [Y/n] y
 - Dropping test database...
 ... Success!
 - Removing privileges on test database...
 ... Success!

Reloading the privilege tables will ensure that all changes made so far
will take effect immediately.

Reload privilege tables now? [Y/n] y
 ... Success!

Cleaning up...

Once you’re done with that you can finish up by installing PHP.

Step 3: Install PHP

PHP is an open source web scripting language that is widely use to build dynamic webpages.

To install PHP, open terminal and type in this command.

sudo apt-get install php5 libapache2-mod-php5 php5-mcrypt

After you answer yes to the prompt twice, PHP will install itself.

It may also be useful to add php to the directory index, to serve the relevant php index files:

sudo nano /etc/apache2/mods-enabled/dir.conf

Add index.php to the beginning of index files. The page should now look like this:

<IfModule mod_dir.c>

          DirectoryIndex index.php index.html index.cgi index.php index.xhtml index.htm


PHP Modules

PHP also has a variety of useful libraries and modules that you can add onto your virtual server. You can see the libraries that are available.

apt-cache search php5-

Terminal will then display the list of possible modules. The beginning looks like this:

php5-cgi - server-side, HTML-embedded scripting language (CGI binary)
php5-cli - command-line interpreter for the php5 scripting language
php5-common - Common files for packages built from the php5 source
php5-curl - CURL module for php5
php5-dbg - Debug symbols for PHP5
php5-dev - Files for PHP5 module development
php5-gd - GD module for php5
php5-gmp - GMP module for php5
php5-ldap - LDAP module for php5
php5-mysql - MySQL module for php5
php5-odbc - ODBC module for php5
php5-pgsql - PostgreSQL module for php5
php5-pspell - pspell module for php5
php5-recode - recode module for php5
php5-snmp - SNMP module for php5
php5-sqlite - SQLite module for php5
php5-tidy - tidy module for php5
php5-xmlrpc - XML-RPC module for php5
php5-xsl - XSL module for php5
php5-adodb - Extension optimising the ADOdb database abstraction library
php5-auth-pam - A PHP5 extension for PAM authentication

Once you decide to install the module, type:

sudo apt-get install name of the module

You can install multiple libraries at once by separating the name of each module with a space.

Congratulations! You now have LAMP stack on your droplet!

Step 4: RESULTS — See PHP on your Server

Although LAMP is installed, we can still take a look and see the components online by creating a quick php info page

To set this up, first create a new file:

sudo nano /var/www/info.php

Add in the following line:


Then Save and Exit.

Restart apache so that all of the changes take effect:

sudo service apache2 restart

Finish up by visiting your php info page (make sure you replace the example ip address with your correct one):