Modern dump technology and protection measures [Ms-Rem] (complete)

Source: Internet
Author: User

Purpose

We all like to use free software, which means someone needs to crack them. When cracking, various shells and protectors must be dealt. The working principle of shell and the basic method of shelling are well explained in Packer final (NEOx, Volodya. This article describes in detail the PE file format and how protectors uses it. Undoubtedly, dump is an important part in the shelling process. The dump acquisition and anti-dump methods are also introduced in those articles, and all the anti-dumping methods in these PE Tools mentioned can be bypassed. However, unfortunately, all these methods can only be used for simple protection, while more complex protectors (eXtreme Protector, Armadillo) use completely different anti-dump methods, PE Tools is already a little pale. In this article, I want to study the modern anti-dump method and the bypass method. This is useful for those who want to learn how to take off shells that are more complex than ASPack.

Anti-dump under ring 0

All process dumpers are implemented by functions such as OpenProcess/ReadProcessMemory/VirtualQueryEx. To obtain the list of modules loaded by a process, you usually use the ToolHelp API. The ToolHelp API function uses ReadProcessMemory to read the memory of the process. At the NativeAPI level, ZwOpenProcess and ZwReadVirtualMemory functions are called. A clear anti-dump method is to create a driver to intercept these functions in kernel mode and prohibit them from accessing the protected process.

The simplest way is to intercept only the ZwOpenProcess function, because to read the process memory, you must first open the process. HOOK handler is generally like this:

NTSTATUS NewNtOpenProcess (
Out phandle ProcessHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN PCLIENT_ID ClientId OPTIONAL)
{
HANDLE ProcessId;

If (ULONG) ClientId> * MmUserProbeAddress) return STATUS_INVALID_PARAMETER;
_ Try
{
ProcessId = ClientId-> UniqueProcess;
}
_ Handler T (EXCEPTION_EXECUTE_HANDLER)
{
DPRINT ("Exception ");
Return STATUS_INVALID_PARAMETER;
}

If (IsAdded (wLastItem, ProcessId ))
{
DPRINT ("Access Denied! ");
Return STATUS_ACCESS_DENIED;
} Else

Return TrueNtOpenProcess (ProcessHandle, DesiredAccess,
ObjectAttributes, ClientId );
}

This code first uses an insurance method to retrieve the ProcessID of the process to be opened, and then determines whether the control is passed or the STATUS_ACCESS_DENIED is returned. Because there may be more than one protected process in the system, you must create a process list, add a new process to it, and delete the completed process. To create this list, we will describe the structure of the protected process:

Typedef struct _ ProcessList
{
PVOID NextItem;
HANDLE Pid;
} TProcessList, * PProcessList;

The code for managing the structure linked list is as follows:

BOOLEAN IsAdded (PProcessList List, HANDLE Pid)
{
PProcessList Item = List;
While (Item)
{
If (Pid = Item-> Pid) return TRUE;
Item = Item-> NextItem;
}
Return FALSE;
}

Void DelItem (PProcessList * List, HANDLE Pid)
{
PProcessList Item = * List;
PProcessList Prev = NULL;
While (Item)
{
If (Pid = Item-> Pid)
{
If (Prev) Prev-> NextItem =
Item-> NextItem; else * List = Item-> NextItem;
ExFreePool (Item );
Return;
}
Prev = Item;
Item = Item-> NextItem;
}
Return;
}


Void FreePointers (PProcessList List)
{
PProcessList Item = List;
PVOID Mem;
While (Item)
{
Mem = Item;
Item = Item-> NextItem;
ExFreePool (Mem );
}
Return;
}


Void AddItem (PProcessList * List, HANDLE Pid)
{
PProcessList wNewItem;
WNewItem = ExAllocatePool (NonPagedPool, sizeof (TProcessList ));
WNewItem-> NextItem = * List;
* List = wNewItem;
WNewItem-> Pid = Pid;
Return;
}

When a new process is found, we will use IOCTL to send a request to the driver to add the process to the linked list, and delete it in the same way after completion. The complete code for implementing the anti-dump driver is located in the Attachment Program in this article.

More reliable protection is to intercept ZwReadVirtualMemory/ZwWriteVirtualMemory and ZwCreateThread, but in this way, the ProcessID must be obtained through the process handle. To this end, you can use the ZwQueryInformationProcess function, but this method does not work for handles with the PROCESS_QUERY_INFORMATION access flag,
Therefore, it is best to use ObReferenceObjectByHandle to obtain the EPROCESS struct pointer and then retrieve ProcessID from the EPROCESS struct directly. The Code is as follows:

ULONG GetPid (HANDLE PHanlde)
{
NTSTATUS st = 15;
PEPROCESS process = 0;
ULONG pId;

St = ObReferenceObjectByHandle (PHanlde, 0, NULL, UserMode, & process, NULL );

If (st = STATUS_SUCCESS)
{
PId = * (PULONG) (ULONG) process) + pIdOffset );

ObDereferenceObject (process );

Return pId;
}
Return 0;
}

PIdOffset-ProcessId offset in the EPROCESS struct. This constant is different in the kernel of different versions of the system. Therefore, when the driver starts, check the kernel version and assign values to the variable. When writing handler, consider that if the process tries to use ZwOpenProcess to open itself, it should also work (compared to PsGetCurrentProcessId ), when processing a function that receives a handle, consider the existence of a pseudo handle (-1) that represents the current process.

It is easy to start with theory, but it is a stumbling block in practice. For example, there is a style service in Windows XP. To allow the sub-system service (csrss.exe) to access the memory of the protected process. The problem arises-how to determine the Id of the process? This problem seems simple at the beginning, but it is not. If the process name is used to determine whether a csrss.exe process can be stopped in the system (for example, cracker can also name its dumper), a more reliable and unique method is required to determine the process. For this reason, I decided to use this method. The subsystem sever has some named objects which can be used to determine the process. For example, we take the LPC Port WindowsApiPort, which is created by csrss on all versions of Windows NT. To determine whether it needs to use ZwQuerySystemInformation to enumerate all opened handles, copy them to the Kernel Handle table, call ZwQueryObject, and compare the obtained names with those found. If they are consistent, the Id of the process that owns the handle is csrss. The following is the implementation code:

PVOID GetInfoTable (ULONG ATableType)
{
ULONG mSize = 0x4000;
PVOID mPtr = NULL;
NTSTATUS St;

Do
{
MPtr = ExAllocatePool (PagedPool, mSize );

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.