找回密码
 加入我们

QQ登录

只需一步,快速开始

搜索
查看: 2420|回复: 1

[转载]CreateRemoteThreadEx

[复制链接]

857

主题

2632

回帖

2

精华

管理员

此生无悔入华夏,  长居日耳曼尼亚。  

积分
36130
发表于 2010-11-3 13:12:04 | 显示全部楼层 |阅读模式
// Sample code that shows how to call CreateRemoteThread with
// multiple parameters.
//
// Coded by. Defsanguje [July 26 2008]
#include <stdio.h>
#include <windows.h>

using namespace std;

////////////////////////////////////////////////////////////////////////////////
// "Extended" version of CreateRemoteThread. Supports multiple parameters and //
// handles parameter passing.                                                 //
////////////////////////////////////////////////////////////////////////////////
// Parameters:                                                                //
//                                                                            //
// - __in HANDLE hProcess                                                     //
//   A handle to the process in which the thread is to be created             //
// - __in LPSECURITY_ATTRIBUTES lpThreadAttributes                            //
//   A pointer to a SECURITY_ATTRIBUTES structure that specifies a security   //
//   descriptor for the new thread. If lpThreadAttributes is NULL, the thread //
//   gets a default security descriptor.                                      //
// - __in SIZE_T dwStackSize                                                  //
//   The initial size of the stack, in bytes. The system rounds this value to //
//   the nearest page. If this parameter is 0 (zero), the new thread uses the //
//   default size for the executable.                                         //
// - __in LPTHREAD_START_ROUTINE lpStartAddress                               //
//   A pointer to the application-defined function of type                    //
//   LPTHREAD_START_ROUTINE to be executed by the thread and represents the   //
//   starting address of the thread in the remote process. The function must  //
//   exist in the remote process.                                             //
// - __in DWORD dwCreationFlags                                               //
//   The flags that control the creation of the thread.                       //
//   (0, CREATE_SUSPENDED, STACK_SIZE_PARAM_IS_A_RESERVATION)                 //
// - __out LPDWORD lpThreadId                                                 //
//   A pointer to a variable that receives the thread identifier. Can be NULL //
// - __in LPSTR szFormat                                                      //
//   Similar to format in printf/scanf. Specifies types of arguments.         //
//   There's three different specifiers for szFormat:                         //
//   %x/%u/%d - DWORD, 4 bytes, value passed directly to the thread           //
//   %[num]d  - Write num bytes from argument to remote process, pass pointer //
//            - to the data for the thread  (ex. %10d)                        //
//   %s       - Write ASCII string to remote process, pass pointer to the     //
//              string for the thread                                         //
////////////////////////////////////////////////////////////////////////////////
// Remarks:                                                                   //
//                                                                            //
// Threads that exits using TerminateThread(), ExitThread() or similar doesn't//
// free memory that's allocated for "callgate"                                //
////////////////////////////////////////////////////////////////////////////////
HANDLE
CreateRemoteThreadEx(HANDLE hProcess, LPSECURITY_ATTRIBUTES lpThreadAttributes,
                     SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress,
                     DWORD dwCreationFlags, LPDWORD lpThreadId,
                     LPSTR szFormat, ...)
{
    char *lpCallGate,
         *lpData,
         *lpCode,
         *lpArg;
    va_list vlParameters;
    BYTE i, j;
    DWORD dwDataSize,
          dwCallSize,
          dwWritten,
          dwAmount = 0; // amount of parameters

    char CallGateShellcode[] = "\xE8\x1D\x00\x00\x00" // CALL $+0x1D
                           /*/*/
                          /*|*/"\x50"                 // PUSH EAX
                          /*|*/"\x68\x58\x58\xC3\x90" // PUSH 90C35858 (code for POP EAX\nPOP EAX\nRETN)"
                          /*|*/"\x68\x00\x40\x00\x00" // PUSH MEM_RELEASE
                          /*|*/"\x6A\x01"             // PUSH 1
                          /*|*/"\x68\x00\x00\x00\x00" // PUSH 00000000 (-> PUSH lpCallGate)
                          /*|*/"\x54"                 // PUSH ESP
                          /*|*/"\x83\x04\x24\x0C"     // ADD DWORD [ESP], 0x0C
                          /*|*/"\x68\x00\x00\x00\x00" // PUSH 00000000 (-> PUSH VirtualFree)
                          /*|*/"\xC3"                 // RETN
                           /*\*/
                               "\x68\x00\x00\x00\x00" // PUSH 00000000 (-> PUSH lpStartAddress)
                               "\xC3"                 // RETN
                               ;
     
    // Calculate the size of our callgate. Depends on
    // amount of parameters.
     
    if(szFormat)
    {
        // Count %'s
        for(i = 0; szFormat != '\0'; i++)
            if(szFormat == '%')
                dwAmount++;
     
        // Calculate size of data (%s, %[num]d)
        i = 0;
        dwDataSize = 0;
        va_start(vlParameters, dwAmount);
        while(szFormat != '\0')
        {
            if(szFormat != '%')
                return NULL;
            i++;
         
            switch(szFormat)
            {
                case 'd':
                case 'u':
                case 'x':
                    va_arg(vlParameters, DWORD);
                    break;
                case 's':
                    dwDataSize += lstrlen(va_arg(vlParameters, char*)) + 1;
                    break;
                default: // number?
                    // Conversion from string to integer
                    for(j = 0; szFormat >= '0' && szFormat <= '9'; i++)
                        j = j * 10 + szFormat - '0';
                    if(!j || szFormat != 'd') return 0; // Converting failed
                 
                    va_arg(vlParameters, char*);
                    dwDataSize += j;
                    break;
            }
            i++;
        }
        va_end(vlParameters);
    } // if(szFormat)
     
    dwCallSize = dwAmount * (4+1)             // Size of  PUSH instructions
                 + dwDataSize                 // %s, %d
                 + sizeof(CallGateShellcode);
     
    // Allocate memory for callgate constructing (local process)
    char* lpShellcodeBuffer = (char*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwCallSize);
    if(!lpShellcodeBuffer)
        return NULL;
     
    // Allocate memory from remote process
    lpCallGate = (char*)VirtualAllocEx(hProcess, NULL, dwCallSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    if(!lpCallGate)
    {
        HeapFree(GetProcessHeap(), 0, lpShellcodeBuffer);
        return NULL;
    }
     
    // Construct it. Copy data/strings to beginning of the buffer,
    // code to the end.
    va_start(vlParameters, dwAmount);
    lpData = lpShellcodeBuffer;
    lpCode = lpShellcodeBuffer + dwDataSize + dwAmount * (1+4);
    i = 0;
    if(szFormat)
    {
        while(szFormat != '\0')
        {
            i++; // %
            switch(szFormat)
            {
                case 'd':
                case 'u':
                case 'x':
                    lpCode -= 5; // due to calling conventions
                    (*lpCode)           = 0x68; // PUSH
                    *(DWORD*)(lpCode+1) = (DWORD)va_arg(vlParameters, DWORD);
                    break;
                case 's':
                    lpArg = va_arg(vlParameters, char*);
                    j = lstrlen(lpArg) + 1;
                    break;
                default:
                    // Conversion from string to integer
                    lpArg = va_arg(vlParameters, char*);
                    for(j = 0; szFormat >= '0' && szFormat <= '9'; i++)
                        j = j * 10 + szFormat - '0';
                    break;
            }
            if(szFormat == 's' || szFormat == 'd')
            {
                lpCode -= 5;
                (*lpCode)           = 0x68;
                *(DWORD*)(lpCode+1) = (DWORD)(lpCallGate + (lpData-lpShellcodeBuffer));
            
                while(j)
                {
                    (*lpData) = *lpArg;
                    lpData++, lpArg++;
                    j--;
                }
            }
            i++; // xsd
        }
        va_end(vlParameters);
    } // if(szFormat)
     
    // Copy the shellcode
    // (it's responsible to push arguments to stack, virtualfree itself, call the thread)
    lpCode = lpShellcodeBuffer + dwDataSize + dwAmount * (1+4);
    *(DWORD*)(CallGateShellcode + 19) = (DWORD)lpCallGate;
    *(DWORD*)(CallGateShellcode + 35) = (DWORD)lpStartAddress;
    *(DWORD*)(CallGateShellcode + 29) = (DWORD)GetProcAddress(GetModuleHandle("kernel32.dll"), "VirtualFree");
    for(i = 0; i < sizeof(CallGateShellcode); i++, lpCode++)
       (*lpCode) = CallGateShellcode;
     
    // Write the shellcode to remote process and call it
    WriteProcessMemory(hProcess, lpCallGate, lpShellcodeBuffer, dwCallSize, &dwWritten);     
    HeapFree(GetProcessHeap(), 0, lpShellcodeBuffer);
     
    if(!dwWritten)
        return NULL;
    return CreateRemoteThread(hProcess, lpThreadAttributes, dwStackSize,
                              (LPTHREAD_START_ROUTINE)(lpCallGate + dwDataSize), 0,
                              dwCreationFlags, lpThreadId);
}

int main(int argc, char *argv[])
{
    char szWnd[256];
    HANDLE hProcess = NULL, hThr = NULL;
    HWND hWnd = NULL;
    DWORD dwPID = 0, dwExitCode;
    printf("Boring CreateRemoteThreadEx() demo\n");
     
    do
    {
        printf("Give window (not process) name\n");
         
        // whitespaces also
        scanf("%255[^\t\n]", szWnd);
        while(getchar() != (int)'\n');
         
        GetWindowThreadProcessId(FindWindow(NULL, szWnd), &dwPID);
        if(dwPID)
        {
            hProcess =
            OpenProcess(
                        PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION
                        | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ,
                        FALSE,
                        dwPID
                        );
        } else printf ("FindWindow(); failed\n");
    } while(!hProcess);
     
    hThr = CreateRemoteThreadEx(hProcess, NULL, 0,
                                (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle("user32.dll"), "MessageBoxA"),
                                0, NULL,
                                "%x%s%8d%x",
                                NULL, "Hello world", "Caption", MB_ICONEXCLAMATION | MB_YESNOCANCEL);
    /*hThr = CreateRemoteThreadEx(hProcess, NULL, 0,
                                (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle("kernel32.dll"), "GetTickCount"),
                                0, NULL,
                                NULL); // "");*/

     
    CloseHandle(hProcess);
     
    if(hThr)
    {
        printf("Created remote thread succesfully!\n"
               "Waiting for thread exit code...\n");
        WaitForSingleObject(hThr, INFINITE);
        GetExitCodeThread(hThr, &dwExitCode);
        CloseHandle(hThr);
        printf("Thread exited with code: %d\n", dwExitCode);
    } else printf("Remote thread creation failed!");
     
    system("PAUSE");
    return EXIT_SUCCESS;
}

857

主题

2632

回帖

2

精华

管理员

此生无悔入华夏,  长居日耳曼尼亚。  

积分
36130
 楼主| 发表于 2010-11-3 13:14:50 | 显示全部楼层
原始出处:http://www.rohitab.com/discuss/t ... reateremotethreadex;/

createremotethreadex.zip

6.83 KB, 阅读权限: 10, 下载次数: 2

售价: 1 水晶币  [记录]

您需要登录后才可以回帖 登录 | 加入我们

本版积分规则

快速回复 返回顶部 返回列表