Run two programs in the same process space

Source: Internet
Author: User
According to Zhou Zhi, bo2kcan run as a thread in a specified path space (such as the assumer.exe process. This article attempts to find a way to make any exe run in other processes as a thread (of course, the "arbitrary" mentioned here is conditional and will be discussed below ).

For the sake of simplicity, I call the first loaded exe as the host, and the later loaded exe as the customer. For example, assume that er.exeis the parent and bo2k.exe is the customer.

 

Basic knowledge

Each exe has a default load base address, usually 0x400000. If the actual loading base address is the same as the default base address, you do not need to fix the relocated table in the program. Otherwise, you must modify the relocated table;

If a program does not relocate a table, and the program cannot run if it cannot be loaded at the default base address. For example, the minimum load base address of Windows 95 is 0x400000. You have developed an exe on Windows NT and specified that the load base address is 0x10000, if the connector is stripped from the relocation table during connection, it cannot run under Windows 95.

To avoid conflicts with common programs, bo2k selects an extremely special base address: 0x03140000, which is generally not used by programs. In this way, after bo2k is started, use WriteProcessMemory to copy itself to the 0x03140000 address of the host process, and then use CreateRemoteThread to remotely start a thread and execute it from the entry point.

Bo2k can run normally in other process spaces. There are two key points:

1) The actual loading base address is the same as the default base address, so you do not need to modify the relocation table.

2) the dynamic Connection Library of implicitly link is consistent with the loading base address in the target process and the loading base address at bo2k startup, so that you do not need to modify the import function table. Unless you only use ntdll. dll and kernel32.dll,

Otherwise, this is hard to guarantee. The solution of bo2k is that code running remotely does not need to be called implicitly. All APIs used are dynamically determined after the code is run remotely (using LoadLibrary and GetProcAddress)

 

My goal is to make "all" programs run in other process spaces. Here, "all" means all the executable programs in the 32-bit PE format that "the relocation table is not stripped.

For visual C ++, this includes all Debug Programs and release programs linked with the "/fixed: No" option.

For general programs, the above two points are hard to meet:

1) The base address for loading the vast majority of programs is 0x400000. In this way, it is difficult for the client EXE to ensure that it is loaded to its default base address. The solution is to correct the relocated table. If, unfortunately, the relocation table of this EXE is stripped, this EXE cannot run in other process spaces.

For visual C ++, the strip relocation table is the default setting of release version exe. You can add "/fixed: No" to the connection options of the project file to prevent the connector from being detached from the relocation table.

2) Many programs use implicit connections to call windows APIs, but few programs only use kernel32.dll to export APIs. Therefore, this is hard to guarantee. The solution is to re-enter the import table ).

In addition, for interface programs, it is not enough to simply correct the relocation and import tables. Because they both directly or indirectly use the getmodulehandle and loadresource functions.

Getmodulehandle has a feature. If the modulename passed to him is null, the module handle of the host EXE is returned. Loadresource is similar. If the module handle passed to it is null, it is considered as the host EXE module. Similar APIs are not listed one by one.

The client exe will obviously get the wrong result when calling these Apis. Therefore, these APIs must be intercepted for special processing.

Based on the above analysis, we need to make the two programs share a process space:

1) Open Process boundaries: Use writeprocessmemory to inject code to the host process and use createremotethread to start remote code;

2) load the client EXE in the remote code and modify the relocation table and fill in the DLL import table if necessary.

3) The GetModuleHandle and LoadResource APIs are intercepted, and the module handle of the client exe is returned when the client exe is called with the default parameter, instead of the host handle.

Based on the above ideas, I wrote remote. dll and exported three functions: RemoteRunA, RemoteRunW, and RemoteCall.

The prototype is:

Bool winapi RemoteRunA (DWORD processId, maid, maid );

Bool winapi RemoteRunW (DWORD processId, maid, maid );

Bool winapi RemoteCall (DWORD processId, PVOID pfnAddr, PVOID pParam, DWORD cbParamSize, BOOL fSyncronize );

RemoteRunA is used to load and execute the client exe in the host process;

RemoteRunW is the unicode version of RemoteRunA;

RemoteCall allows remote injection and code execution.

Call example:

Assume that the master exeis depends.exe (the host process I often use), and the pid is 136. The client exe is "C:/WINNT/system32/CALC. EXE ", RemoteRunA (136," C: // WINNT // system32 // CALC. EXE ", NULL, SW_SHOW );

Or,

RemoteRunW (136, L "C: // WINNT // system32 // CALC. EXE", NULL, SW_SHOW );

RemoteCall is a cool by-product. You can run a series of code carefully prepared by yourself in any host process.

Remote Code does not require special processing, just like local calls. RemoteCall supports many features:

Supports implicit calls to Windows APIs (without dynamic confirmation using LoadLibrary and GetProcAddress)

You can use global/static variables (except dynamic initialization );

Data can be compiled, especially string constants;

Supports exception handling;

Supports source code-level debugging;

Supports synchronous and asynchronous calls;

For synchronous calls, the returned results and error numbers can be obtained;

Exception protection is implemented for remote code, and code execution errors do not cause the host process to crash.

The only drawback of RemoteCall is the low efficiency (of course, your exe must be relocable ).

Call example:

In Windows 2000, SendMessage (hwnd, WM_GETTEXT,...) is called for password-protected Edit control ,...) when trying to get the password content, the system will check whether the process that calls SendMessage is the same as the process where Edit control is located. Otherwise, an empty string is returned and the call fails.

The solution should obviously be to call SendMessage in the target process.

RemoteCall can be easily implemented:

Typedef struct _ tagGETPASS {

HWND hwndPassword; // in

Char szPassText [1024]; // out

} GETPASS;

Static int * _ p = NULL;

BOOL NullFunction (){

// Static variables and exception protection can be used.

_ Try {

* _ P = 0;

}__ Handle T (EXCEPTION_EXECUTE_HANDLER ){}

Return TRUE;

}

// Prepare code to run remotely

Bool winapi RemoteGetPasswordText (GETPASS * pgp ){

// You can use the relative call (near call), which is useless.

NullFunction ();

// Implicitly call Windows APIs

If (SendMessageA (pgp-> hwndPassword, WM_GETTEXT, sizeof (pgp-> szPassText)-1, (LPARAM) pgp-> szPassText ))){

MessageBoxA (NULL,

Pgp-> szPassText,

"Great !! ", // You can use string constants.

MB_ OK );

Return TRUE;

}

Return FALSE;

}

Void GetPasswordText (HWND hwnd ){

GETPASS gp;

Gp. hwndPassword = hwnd;

DWORD processId;

GetWindowThreadProcessId (hwnd, & processId );

HMODULE hLib =: LoadLibrary ("remote. dll ");

If (hLib! = NULL ){

Typedef BOOL (WINAPI * PFN_RemoteCall) (DWORD processId, PVOID pfnAddr, PVOID pParam, DWORD cbParamSize, BOOL fSyncronize );

PFN_RemoteCall fnRemoteCall = (PFN_RemoteCall): GetProcAddress (hLib, "RemoteCall ");

If (fnRemoteCall! = NULL ){

If (fnRemoteCall (processId, RemoteGetPasswordText, & gp, sizeof (gp), TRUE ))

MessageBoxA (NULL, gp. szPassText, "we get the password !! ", MB_ OK );

}

 

: FreeLibrary (hLib );

}

}

 

 

Call example of RemoteRun:

 

Void PrintUsage (){

Printf ("/tUsage: rmExe <target process id> <Exe file path>/n ");

}

 

Int main (int argc, char * argv []) {

If (argc <= 2 ){

PrintUsage ();

Return-1;

}

 

Int pid = atoi (argv [1]);

If (pid! = 0 ){

HMODULE hRemote =: LoadLibrary ("remote. dll ");

If (hRemote! = NULL ){

Typedef DWORD (WINAPI * PFN_RemoteRun) (DWORD processId, LPCSTR lpszAppPath, LPSTR lpszCmdLine, int nCmdShow );

PFN_RemoteRun fnRemoteRun = (PFN_RemoteRun): GetProcAddress (hRemote, "RemoteRunA ");

If (fnRemoteRun! = NULL)

FnRemoteRun (pid, argv [2], NULL, SW_SHOW );

FreeLibrary (hRemote );

}

}

Return 0;

}

 

 

Notes:

1) The most difficult part is to load the client's exe. Simply calling LoadLibrary won't solve the problem at all, and he won't modify the relocation table and import table for you.

In addition, for. tls section (used to support local thread storage) and. bss section (used to initialize data), I am not very clear about how to handle it; I hope someone will discuss it with me;

2) Currently, remote. dll does not support running three or more programs in one process space. The problem is that I maintain the thread list of a client exe in remote. dll,

It is used to determine who has called the GetModuleHandle API. Currently, only one client exe can be processed. This problem is not difficult to solve;

3) There are some tools to view the list of modules loaded in the process. If you want to hide the process completely and do not want these tools to detect our modules, in my opinion, there are at least two solutions:

I. It seems very difficult to write LoadDLL without LoadLibrary. Fortunately, a set of such tools (implemented in dll_load.cpp) is provided in the bo2k source code ).

The code in dll_load.cpp is basically used to modify the relocation table and import table in remote. dll. It is worth noting that there is a bug in the original implementation of dll_load.cpp. He cannot correctly handle the EXE generated by the tlink32 of Borland. For more information, see Matt pietrek's "Windows 95 system programming secrets" or the msdn article: "peering inside the PE: a tour of the Win32 portable Executable File Format ", the difference between Ms linker and Borland linker is discussed.

2. I have developed a method for getting rid of the. exe file and. dll file. The idea is to back up all the data of the EXE or DLL module to be stripped, and then use freelibrary or unmapviewoffile to unload the module,

Recover the backup module. I used to post code on csdn. Find it by yourself.

(4) ms detours package 1.3 is used to intercept the API. I don't want to attach its source code. Download it myself: http://research.microsoft.com/sn/detours

5) other threads must be suspended when the API is intercepted. I used two undisclosed interfaces: ntquerysysteminformation used to enumerate threads; ntopenthread used to get thread handles.

We recommend a tool book: "Windows NT native api reference" (the Chinese name is "Windows NT native api reference"). The title is roughly the same and you don't have to go into it. I was so angry that navtive turned into a local machine that I took you. The book lists the prototype of many native APIs and their data structures. Although the translation is very rough, but this one has no choice, it is worth buying a reference, if you want to study the "local" API ,:).

Example of successful running:

Run calc.exe in the depends.exeprocess;

Run Acrobat 5.0 in the depends.exe process;

Run Microsoft Visio 2000 in the depends.exe process;

Run Process Hacker in the depends.exe Process (a Process viewing tool I wrote myself) and use many low-level interfaces;

Run Acrobat 5.0 in the Process Hacker Process.

 

The only failure example is to run matlab 5.1 as a customer. This executable file is special. It has multiple code sections and data sections, as well as. tls section and. bss section.

The cause of failure is not very clear (mainly because there is not enough time to study). It may be. tls and. the bss section is not properly processed during loading. It may also be that an API for special processing is not intercepted.

 

I am interested in writing this thing. I hope anyone interested will study with me.

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.