Go to: DLL injection method-createremotethread Method

Source: Internet
Author: User

To implement remote thread injection, you must use the createremotethread function provided by windows to create a remote thread.
The function is prototype as follows:
Handle createremotethread (
Handle hprocess,
Lpsecurity_attributes lpthreadattributes,
Size_t dwstacksize,
Lpthread_start_routine lpstartaddress,
Lpvoid lpparameter,
DWORD dwcreationflags,
Lpdword lpthreadid
);

Parameter description:
Hprocess: handle of the target process
Lpthreadattributes: pointer to the thread's security description struct. Generally, it is set to null, indicating that the default security level is used.
Dwstacksize: Specifies the thread stack size. Generally, it is set to 0, indicating that the default size is used. Generally, it is 1 MB.
Lpstartaddress: Address of the thread function
Lpparameter: thread Parameter
Dwcreationflags: thread Creation Method
The create_suincluded thread is created as a pending thread.
Lpthreadid: output parameter, which records the ID of the created remote thread

The createremotethread function has been introduced. For more information, see the description of this function in msdn!
Now that we know how to use this function to create a remote thread, Let's define the thread function body and
Same definition. The thread function of the remote thread must define the static member function or global function of the program class.
For example:
DWORD _ stdcall threadproc (lpvoid lparam)
{
// Here we first define this thread function as a null Function
Return 0;
}
Here we first define the thread function body as null, because it should be used as a remote injection thread, the compiling method of the thread function body and the common thread function.
Slightly different.

Then copy the thread code to the target process address space (the address must be a page with page_execute_readwrite as the page attribute) or
Other host processes can execute (for example, shared memory ing area ). Here we select the host process. When copying the thread body, we need
Use the virtualallocex function to apply for a storage area in the host process, and then use the writeprocessmemory function to write the thread code.
In the host process.

You can use the functions in psapi. h or the toolhelp function to obtain the host process ID.
Functions implemented using toolhelp:

// Obtain the process id based on the process name. If multiple instances are running at the same time, only the ID of the first enumerated process is returned.
DWORD processnametoid (lpctstr lpszprocessname)
{
Handle hsnapshot = createconlhelp32snapshot (th32cs_snapprocess, 0 );
Processentry32 PE;
PE. dwsize = sizeof (processentry32 );

If (! Process32first (hsnapshot, & PE )){
MessageBox (null,
"The frist entry of the Process list has not been copyied to the buffer ",
"Notice", mb_iconinformation | mb_ OK );
Return 0;
}

While (process32next (hsnapshot, & PE )){
If (! Strcmp (lpszprocessname, PE. szexefile )){
Return PE. th32processid;
}
}

Return 0;
}

After completing the preceding steps, you can use createremotethread to create a remote thread! The sample code is as follows:

# Include <windows. h>
# Include <tlhelp32.h>
# Include <iostream>

// The thread function to be inserted into the host process
DWORD _ stdcall threadproc (lpvoid lparam)
{
Return 0;
}

Int main (INT argc, char * argv [])
{
Const Dwords dwthreadsize = 4096;
DWORD dwwritebytes;

STD: cout <"Please input the name of target process" <STD: Endl;
Char szexename [max_path] = {0 };
// Wait for the host process name to be entered
STD: CIN> szexename;

// Obtain the ID of the process with the specified name. If multiple process instances exist, obtain the ID of the first process.
DWORD dwprocessid = processnametoid (szexename );
Handle htargetprocess = OpenProcess (process_all_access, false, dwprocessid)
Void * premotethread = virtualallocex (htargetprocess, 0,
Dwthreadsize, mem_commit | mem_reserve, page_execute_readwrite );
// Write the thread body to the host process
If (! Writeprocessmemory (htargetprocess,
Premotethread, & threadproc, dwthreadsize, 0 )){
MessageBox (null, "write data to target process failed! ",
"Notice", mb_iconinformation | mb_ OK );
Return 0;
}
// Create a thread in the host process
Handle hremotethread = createremotethread (
Htargetprocess, null, 0, (DWORD (_ stdcall *) (void *) premotethread,
Null, 0, & dwwritebytes );
If (! Hremotethread ){
MessageBox (null, "Create remote thread failed! "," Notice ", mb_iconstop );
Return-1;
}
Return 0;
}

When the code above is run, a thread defined by the programmer will be created in the host process, but the thread function is empty now.
Do nothing.
Next we will compile the content of the specific thread function body. Here we simply display a message dialog box MessageBox
The Modified Thread function is as follows:
DWORD _ stdcall threadproc (lpvoid lparam)
{
MessageBox (null, "hello", "hello", mb_ OK );
Return 0;
}

After the thread body is modified, we run the program and inject the thread into the host process. However, an invalid access error occurs. Original
It is the MessageBox (null, "hello", "hello", mb_ OK) in the thread body. The second and third parameters of the Function Point to the string.
Is in the address space of the current process. When a thread in the host process accesses the string "hello", an invalid memory access error occurs.
The solution is to copy the content of the string to the address space of the host process, and use the MessageBox function in user32.dll.
The address is also copied to the host process.
To copy the entry address of the string and MessageBox function to the host process, we first define the remoteparam struct
Stores the entry address of the MessageBox function and the content of the string displayed in MessageBox. The structure is defined as follows:
// Thread parameters
Typedef struct _ remoteparam {
Char szmsg [12]; // string displayed by the MessageBox Function
DWORD dwmessagebox; // entry address of the MessageBox Function
} Remoteparam, * premoteparam;

Remoteparam remotedata;
Zeromemory (& remotedata, sizeof (remoteparam ));

Hinstance huser32 = loadlibrary ("user32.dll ");
Remotedata. dwmessagebox = (DWORD) getprocaddress (huser32, "messageboxa ");
Strcat (remotedata. szmsg, "Hello/0 ");

// Allocate storage space in the host process
Remoteparam * premoteparam = (remoteparam *) virtualallocex (
Htargetprocess, 0, sizeof (remoteparam), mem_commit, page_readwrite );

If (! Premoteparam ){
MessageBox (null, "alloc memory failed! ",
"Notice", mb_iconinformation | mb_ OK );
Return 0;
}

// Write the entry address of the string and MessageBox functions to the host process
If (! Writeprocessmemory (htargetprocess,
Premoteparam, & remotedata, sizeof (remotedata), 0 )){
MessageBox (null, "write data to target process failed! ",
"Notice", mb_iconinformation | mb_ OK );
Return 0;
}

// Create a remote thread
Handle hremotethread = createremotethread (
Htargetprocess, null, 0, (DWORD (_ stdcall *) (void *) premotethread,
Premoteparam, 0, & dwwritebytes );

Note that some system processes cannot use the OpenProcess function when opening a process.
In this case, you need to increase the access permission of the process to access the system process.
I provide a function enabledebugpriv () to improve the process access permission. The function is defined as follows:

// Improve process Access Permissions
Bool enabledebugpriv ()
{
Handle htoken;
Luid sedebugnamevalue;
Token_privileges tkp;

If (! Openprocesstoken (getcurrentprocess (),
Token_adjust_privileges | token_query, & htoken )){
Return false;
}

If (! Lookupprivilegevalue (null, se_debug_name, & sedebugnamevalue )){
Closehandle (htoken );
Return false;
}

Tkp. privilegecount = 1;
Tkp. Privileges [0]. luid = sedebugnamevalue;
Tkp. Privileges [0]. Attributes = se_privilege_enabled;

If (! Adjusttokenprivileges (htoken, false, & tkp, sizeof (tkp), null, null )){
Closehandle (htoken );
Return false;
}

Return true;
}

At this point, the creation of remote threads is all over. The complete code is provided below:

# Pragma once
# Include "stdafx. H"
# Include <windows. h>
# Include <tlhelp32.h>
# Include <iostream>

// Thread parameter struct Definition
Typedef struct _ remoteparam {
Char szmsg [12]; // The character prompt displayed in the MessageBox Function
DWORD dwmessagebox; // entry address of the MessageBox Function
} Remoteparam, * premoteparam;

// Define the function pointer of the MessageBox type
Typedef int (_ stdcall * pfn_messagebox) (hwnd, lpctstr, lpctstr, DWORD );

// Thread Function Definition
DWORD _ stdcall threadproc (lpvoid lparam)
{
Remoteparam * Gp = (remoteparam *) lparam;

Pfn_messagebox pfnmessagebox;
Pfnmessagebox = (pfn_messagebox) PLT-> dwmessagebox;
Pfnmessagebox (null, GP-> szmsg, GP-> szmsg, 0 );

Return 0;
}

// Improve process Access Permissions
Bool enabledebugpriv ()
{
Handle htoken;
Luid sedebugnamevalue;
Token_privileges tkp;

If (! Openprocesstoken (getcurrentprocess (),
Token_adjust_privileges | token_query, & htoken )){
Return false;
}

If (! Lookupprivilegevalue (null, se_debug_name, & sedebugnamevalue )){
Closehandle (htoken );
Return false;
}

Tkp. privilegecount = 1;
Tkp. Privileges [0]. luid = sedebugnamevalue;
Tkp. Privileges [0]. Attributes = se_privilege_enabled;

If (! Adjusttokenprivileges (htoken, false, & tkp, sizeof (tkp), null, null )){
Closehandle (htoken );
Return false;
}

Return true;
}

// Obtain the process id based on the process name. If multiple running instances exist, the ID of the first enumerated process is returned.
DWORD processnametoid (lpctstr lpszprocessname)
{
Handle hsnapshot = createconlhelp32snapshot (th32cs_snapprocess, 0 );
Processentry32 PE;
PE. dwsize = sizeof (processentry32 );

If (! Process32first (hsnapshot, & PE )){
MessageBox (null,
"The frist entry of the Process list has not been copyied to the buffer ",
"Notice", mb_iconinformation | mb_ OK );
Return 0;
}

While (process32next (hsnapshot, & PE )){
If (! Strcmp (lpszprocessname, PE. szexefile )){
Return PE. th32processid;
}
}

Return 0;
}

Int main (INT argc, char * argv [])
{
// Define the size of the thread body
Const Dwords dwthreadsize = 4096;
DWORD dwwritebytes;
// Improve process Access Permissions
Enabledebugpriv ();

// Wait for the input process name. Make sure that the process name is case-insensitive.
STD: cout <"Please input the name of target process! "<STD: Endl;
Char szexename [max_path] = {0 };
STD: CIN> szexename;

DWORD dwprocessid = processnametoid (szexename );

If (dwprocessid = 0 ){
MessageBox (null, "the target process have not been found! ",
"Notice", mb_iconinformation | mb_ OK );
Return-1;
}

// Obtain the Process Handle Based on the process ID
Handle htargetprocess = OpenProcess (process_all_access, false, dwprocessid );

If (! Htargetprocess ){
MessageBox (null, "open target process failed! ",
"Notice", mb_iconinformation | mb_ OK );
Return 0;
}

// Open a storage area for the thread body in the host process
// Pay attention to the mem_commit | mem_reserve memory out-of-configuration type and page_execute_readwrite memory protection type.
// For more information, see the description of virtualallocex function in msdn.
Void * premotethread = virtualallocex (htargetprocess, 0,
Dwthreadsize, mem_commit | mem_reserve, page_execute_readwrite );

If (! Premotethread ){
MessageBox (null, "alloc memory in target process failed! ",
"Notice", mb_iconinformation | mb_ OK );
Return 0;
}

// Copy the thread body to the host process
If (! Writeprocessmemory (htargetprocess,
Premotethread, & threadproc, dwthreadsize, 0 )){
MessageBox (null, "write data to target process failed! ",
"Notice", mb_iconinformation | mb_ OK );
Return 0;
}
// Define the struct variable of the thread Parameter
Remoteparam remotedata;
Zeromemory (& remotedata, sizeof (remoteparam ));

// Fill in the Members in the struct variable
Hinstance huser32 = loadlibrary ("user32.dll ");
Remotedata. dwmessagebox = (DWORD) getprocaddress (huser32, "messageboxa ");
Strcat (remotedata. szmsg, "Hello/0 ");

// Opens the storage area for thread parameters in the host process
Remoteparam * premoteparam = (remoteparam *) virtualallocex (
Htargetprocess, 0, sizeof (remoteparam), mem_commit, page_readwrite );

If (! Premoteparam ){
MessageBox (null, "alloc memory failed! ",
"Notice", mb_iconinformation | mb_ OK );
Return 0;
}

// Copy the thread parameters to the host process address space
If (! Writeprocessmemory (htargetprocess,
Premoteparam, & remotedata, sizeof (remotedata), 0 )){
MessageBox (null, "write data to target process failed! ",
"Notice", mb_iconinformation | mb_ OK );
Return 0;
}

// Create a thread in the host process
Handle hremotethread = createremotethread (
Htargetprocess, null, 0, (DWORD (_ stdcall *) (void *) premotethread,
Premoteparam, 0, & dwwritebytes );

If (! Hremotethread ){
MessageBox (null, "Create remote thread failed! "," Notice ", mb_iconinformation | mb_ OK );
Return 0;
}

Closehandle (hremotethread );

Return 0;
}

 

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.