Você está na página 1de 10

Part 2

Practical Guides on Windows API


hooking

Author:
http://www.kk-wuti.blogspot.com
Copyright: http://kk-wuti.blogspot.com

TABLE OF CONTENTS

Disclaimer .......................................................................................................................... 3
About this guide ................................................................................................................ 3
Pre-exquisite ...................................................................................................................... 3
Method II – Running codes in remote process space..................................................... 4
Section I – Allocate memory, create and run a thread in remote application................. 4
Step 1 – Create a DLL to be loaded by remote process.............................................. 4
Step2: - Inject codes into remote process ................................................................... 5
Section II – Inside the remote process .......................................................................... 10
Summary ....................................................................................................................... 10

2
Copyright: http://kk-wuti.blogspot.com

Disclaimer
THIS INFORMATION IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS INFORMATION, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

About this guide


There are tones of information available regarding windows hooking. As such, this guide
will not go into details of what is Windows Hooking or what it can do for you. This guide
will instead directly jump into the many ways of Windows Hooking and for each method;
a working source codes example with a step by step guide is given. While the author will
paint a picture on where and how a particular method could be used, it is entirely up to
the reader to assess and make his or her own judgment on how a particular method
presented here could best be used with regard to the actual needs.

Pre-exquisite
Familiar with Ms Visual C++ 6.0 tools

3
Copyright: http://kk-wuti.blogspot.com

Method II – Running codes in remote process space


This is a more advanced method of hacking Windows application. This guide and
explanation is divided into two main sections.

Section I – Allocate memory, create and run a thread in remote


application

Briefly, the codes or function to be run in the remote process are residing in a normal
Win32 DLL. In order to force any application to run the codes inside the Win32 DLL that
we have written, first we need to force the application we want to hack to load our Win32
DLL in a separate thread in its (the remote process) own address space. We know that
whenever a DLL is loaded by Windows, DllMain is entered and the codes in
DLL_PROCESS_ATTACH is executed. So it is inside here that we lay our codes to be
run by the remote process. All this doesn’t sound complicated, and here is a step by step
guide in doing it.

Step 1 – Create a DLL to be loaded by remote process

Create a simple WIN32 DLL; let’s call it SimpleDll.dll (You can create it through the
VC++ 6 project wizard). You DllMain function should look similar to the following: -

CODE:

BOOL APIENTRY DllMain( HANDLE hModule,


DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{

//HERE is where we are going to lay our function to be run by the remote process

}
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}

4
Copyright: http://kk-wuti.blogspot.com

Step2: - Inject codes into remote process

Create an application to “inject” or copy your codes into the remote application you are
targeting. This can be any MFC or even non-windows application. Create a function
inside the application to do the following codes injection.

This is the core part of the method and as such, there are a few important concepts and
twists need to be aware of. A bottom up explanation is these: -

As mentioned in the beginning, we need to force the remote application to load our DLL.
The remote application has its own list of tasks to do. So we don’t interfere with its main
thread. To achieve our purpose, we instead ask the remote application to spawn a new
thread. This new thread will do nothing other than loading the DLL (SimpleDll.dll) that
we have created earlier. The function we use to achieve this is CreateRemoteThread
Windows API.

CODE:

HMODULE hKernel32 = GetModuleHandle(__TEXT("kernel32"));


if (hUser32 == NULL)
return 0;

hThread = ::CreateRemoteThread( hProcess, NULL, 0,


(LPTHREAD_START_ROUTINE) ::GetProcAddress(hKernel32,"LoadLibraryA"), pLibRemote, 0, NULL );

From MSDN:

HANDLE WINAPI CreateRemoteThread(


__in HANDLE hProcess,
__in LPSECURITY_ATTRIBUTES lpThreadAttributes,
__in SIZE_T dwStackSize,
__in LPTHREAD_START_ROUTINE lpStartAddress,
__in LPVOID lpParameter,
__in DWORD dwCreationFlags,
__out LPDWORD lpThreadId );

hProcess
A handle to the process in which the thread is to be created.

So we need to pass the process handle of the remote process. It is easy to get that handle.
All we need is to get the process ID of the remote process. Assuming we want to target a
Window application, all we need is the following lines of codes to get the remote process
handle: -

5
Copyright: http://kk-wuti.blogspot.com

CODE:

int PID;

//hWnd is your windows application handler


::GetWindowThreadProcessId( hWnd, (DWORD*)&PID );

//Getting the remote process handler


hProcess = ::OpenProcess( PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION |
PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ,
FALSE, PID);

if (hProcess == NULL) return 0;

lpStartAddress

According to MSDN, this represents the starting address of the thread in the remote
process.

::GetProcAddress(hKernel32,"LoadLibraryA")

If you are aware of, since we are calling this function in our application, the address
returned may not be in the right context when this value is passed in to the remote
application or process. Fortunately, all windows processes somehow always load the
kernel32.dll at the same address. This is so for all the function exported functions from
kernel32.dll. Consequently there is no issue in passing our LoadLibrary’s function
address to the remote process as the remote process will be interpreting this value
correctly as we want it to.

lpParameter

From MSDN: -

This is a pointer to a variable to be passed to the thread function.

Firstly, what data need to be passed into the remote thread? As if creating a thread in a
normal application, it is the parameter to the function of the remote process that needs to
be passed in.

The standard thread function looks like this: -

CODE:

ThreadFunc (LPVOID lpParam)

6
Copyright: http://kk-wuti.blogspot.com

The thread function that we want the remote process to execute should have the same
signature as the normal thread function. And the remote thread function that we want to
execute here is non-other than the LoadLibrary function, and this function’s signature is
similar to that of thread function.

HMODULE WINAPI LoadLibrary( __in LPCTSTR lpFileName );

So in this case, the LoadLibrary’s input parameter is treated as the parameter given to the
remote thread function, similar to the lpParam in ThreadFunc.

To summarize, we will be using CreateRemoteThread function to create a worker thread


in the remote process, passing in the address of the “thread procedure” (LoadLibrary) and
the data/value of “thread parameter” (which is the path of the DLL to be used by
LoadLibrary). In other words, LoadLibrary (lpFileName) is now a mock of the actual
ThreadFunc(lpParam).

Caution: As mentioned before, the same address value in different processes refers to
different thing. Since the address of LoadLibrary is the same in both our application
and in the remote, there is nothing to worry. However, this is not the case for the
“thread parameter” or path of the DLL that we pass into the remote process!!

Since the pointer value of our application could be pointing to different things when it is
interpreted in the remote process, it is thus obvious that the value of this pointer pointing
to should be some value allocated in the remote space rather than value allocated in our
application’s address space. So the question is how do we allocate memory in the remote
address? This is achieved through Windows API VirtualAllocEx.

CODE:

TCHAR szLibPath[]="c:\\SimpleDll.dll";

//Allocate memory in the remote space


void * pLibRemote = ::VirtualAllocEx( hProcess, NULL, sizeof(szLibPath), MEM_COMMIT,
PAGE_READWRITE );

if( pLibRemote == NULL )


return false;

//Write the data into the memory allocated


::WriteProcessMemory(hProcess, pLibRemote, (void*)szLibPath,sizeof(szLibPath),NULL);

7
Copyright: http://kk-wuti.blogspot.com

Up to this point, the function to inject codes into the remote process should look similar
to the following: -

8
Copyright: http://kk-wuti.blogspot.com

CODE:
//hWnd is the Windows handler of the remote process window
int WriteCodesIntoRemoteProcess (HWND hWnd)
{
int PID;
hKernel32 = GetModuleHandle(__TEXT("kernel32"));
if (hKernel32 == NULL)
return 0;

::GetWindowThreadProcessId( hWnd, (DWORD*)&PID );

//Getting the remote process handler


hProcess = ::OpenProcess( PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION |
PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ,
FALSE, PID);

if (hProcess == NULL) return 0;

__try {

// 1. Allocate memory in the remote process for my dll name path


// 2. Write szLibPath to the allocated memory
TCHAR szLibPath[]="c:\\SimpleDll.dll";

//Allocate memory in the remote space


void * pLibRemote = ::VirtualAllocEx( hProcess, NULL, sizeof(szLibPath), MEM_COMMIT,
PAGE_READWRITE );

if( pLibRemote == NULL )


return false;

//Write the data into the memory allocated


::WriteProcessMemory(hProcess, pLibRemote, (void*)szLibPath,sizeof(szLibPath),NULL);

//Create the remote thread and begin execution


hThread = ::CreateRemoteThread( hProcess, NULL, 0,
(LPTHREAD_START_ROUTINE) ::GetProcAddress(hUser32,"LoadLibraryA"),
pLibRemote, 0, NULL );

WaitForSingleObject(hThread, INFINITE);
GetExitCodeThread(hThread, (PDWORD) &nSuccess);
if ( nSuccess )
::MessageBeep(MB_OK);

__finally {
if( !nSuccess )// failed? -> deallocate memory
VirtualFreeEx( hProcess, pDataRemote, 0, MEM_RELEASE );
if ( hThread != 0 )
CloseHandle(hThread);
}
CloseHandle( hProcess );
return nSuccess;

9
Copyright: http://kk-wuti.blogspot.com

Section II – Inside the remote process

Summary

Now that our DLL is loaded by the remote thread, the codes inside the SimpleDll.dll
should be running by the remote process and within the remote process space. We can do
whatever we want to do just like any other thread created by the remote process. While
thread created directly by the remote process may have for instance a Windows object
inside the remote process directly passed in from the main thread, here we are not able to
do that. The parameter we passed in to the thread that we have just created using
CreateRemoteThread is just the path to the SimpleDll.dll.

To be continued in Practical guides to Windows API hooking Part 3.

10

Você também pode gostar