是否可以调用驻留在exe中的非导出函数?

时间:2012-05-07 18:29:27

标签: c windows assembly x86 reverse-engineering

我想调用驻留在第三方.exe中的函数并获取其结果。似乎应该是一种方式,只要我知道函数地址,调用约定等...但我不知道如何。

有谁知道我会怎么做?

我意识到任何解决方案都是非标准的黑客,但必须成为一种方式!


我的非恶意用例:我正在为我的软件逆向工程文件格式。这个函数的计算过于复杂,我的小脑子无法弄清楚;我已经能够将汇编代码直接拉到我自己的DLL中进行测试,但当然我无法释放它,因为那样会被窃取。我将假设用户已预先安装了此特定应用程序,因此我的软件将运行。

3 个答案:

答案 0 :(得分:11)

这是可能的,但不是微不足道的。是的,这是一个非常肮脏的黑客。

在某些情况下,使用LoadLibrary加载EXE文件就足够了。返回的HMODULE实际上是加载的EXE的基地址。将它转换为合适的int类型,将相对函数地址添加到该类型,将其强制转换为函数指针并通过该指针调用该函数。

不幸的是,EXE文件可能会删除其重定位信息。这意味着EXE将期望从特定地址运行。在这种情况下,您必须更改自己程序的基址以避免冲突。查看链接器的文档,应该有一个选项来执行此操作。之后,LoadLibrary将在其首选基址中加载EXE,并希望所有这些都能正常工作。

这个here有一些非常有用的信息。请务必查看页面末尾的更新,了解在某些情况下可能效果更好的其他技术。

编辑:正如Alex在下面的评论中正确指出的那样,如果函数依赖于某个初始值,或者它调用了这样一个函数,包括大多数C运行时函数,那么它将更难这行得通。可以识别初始化函数并事先调用它们,但在这些情况下使用debug API可能是最好的选择。

答案 1 :(得分:8)

好的,我已经整理了原型。

该程序将自身的另一个实例创建为已调试的子进程。

在main()和CRT初始化代码之前将遇到自动断点。这是我们可以更改调试过程的内存和寄存器,使其执行感兴趣的功能。这就是该计划的作用。

它会尝试捕获并处理所有不良情况(例如意外异常)并将其报告为错误。

一个糟糕的情况实际上是一个好的情况。这是程序进入调试过程的UD2指令的#UD异常。在感兴趣的函数返回后,它使用此#UD来停止进程执行。

还有一些说明:

  1. 此代码仅限32位。我甚至没有尝试使其64位可编译或支持64位子进程。

  2. 此代码可能会泄漏句柄。请参阅MSDN上的Windows调试API函数说明,以了解它们需要关闭的位置。

  3. 此代码仅是概念证明,不支持通过EAX,ECX和EDX以外的指针或寄存器传递和返回数据。你必须根据需要扩展它。

  4. 此代码需要一些权限才能创建并完全调试进程。如果您的程序用户不是管理员,您可能不得不担心这一点。

  5. 享受。

    代码:

    // file: unexported.c
    //
    // compile with Open Watcom C/C++: wcl386 /q /wx /we /s unexported.c
    //   (Note: "/s" is needed to avoid stack check calls from the "unexported"
    //    functions, these calls are through a pointer, and it'll be
    //    uninitialized in our case.)
    //
    // compile with MinGW gcc 4.6.2: gcc unexported.c -o unexported.exe
    #include <windows.h>
    #include <stdio.h>
    #include <string.h>
    #include <stdarg.h>
    #include <limits.h>
    
    #ifndef C_ASSERT
    #define C_ASSERT(expr) extern char CAssertExtern[(expr)?1:-1]
    #endif
    
    // Compile as a 32-bit app only.
    C_ASSERT(sizeof(void*) * CHAR_BIT == 32);
    
    #define EXC_CODE_AND_NAME(X) { X, #X }
    
    const struct
    {
      DWORD Code;
      PCSTR Name;
    } ExcCodesAndNames[] =
    {
      EXC_CODE_AND_NAME(EXCEPTION_ACCESS_VIOLATION),
      EXC_CODE_AND_NAME(EXCEPTION_ARRAY_BOUNDS_EXCEEDED),
      EXC_CODE_AND_NAME(EXCEPTION_BREAKPOINT),
      EXC_CODE_AND_NAME(EXCEPTION_DATATYPE_MISALIGNMENT),
      EXC_CODE_AND_NAME(EXCEPTION_FLT_DENORMAL_OPERAND),
      EXC_CODE_AND_NAME(EXCEPTION_FLT_DIVIDE_BY_ZERO),
      EXC_CODE_AND_NAME(EXCEPTION_FLT_INEXACT_RESULT),
      EXC_CODE_AND_NAME(EXCEPTION_FLT_INVALID_OPERATION),
      EXC_CODE_AND_NAME(EXCEPTION_FLT_OVERFLOW),
      EXC_CODE_AND_NAME(EXCEPTION_FLT_STACK_CHECK),
      EXC_CODE_AND_NAME(EXCEPTION_FLT_UNDERFLOW),
      EXC_CODE_AND_NAME(EXCEPTION_ILLEGAL_INSTRUCTION),
      EXC_CODE_AND_NAME(EXCEPTION_IN_PAGE_ERROR),
      EXC_CODE_AND_NAME(EXCEPTION_INT_DIVIDE_BY_ZERO),
      EXC_CODE_AND_NAME(EXCEPTION_INT_OVERFLOW),
      EXC_CODE_AND_NAME(EXCEPTION_INVALID_DISPOSITION),
      EXC_CODE_AND_NAME(EXCEPTION_NONCONTINUABLE_EXCEPTION),
      EXC_CODE_AND_NAME(EXCEPTION_PRIV_INSTRUCTION),
      EXC_CODE_AND_NAME(EXCEPTION_SINGLE_STEP),
      EXC_CODE_AND_NAME(EXCEPTION_STACK_OVERFLOW),
      EXC_CODE_AND_NAME(EXCEPTION_GUARD_PAGE),
      EXC_CODE_AND_NAME(DBG_CONTROL_C),
      { 0xE06D7363, "C++ EH exception" }
    };
    
    PCSTR GetExceptionName(DWORD code)
    {
      DWORD i;
    
      for (i = 0; i < sizeof(ExcCodesAndNames) / sizeof(ExcCodesAndNames[0]); i++)
      {
        if (ExcCodesAndNames[i].Code == code)
        {
          return ExcCodesAndNames[i].Name;
        }
      }
    
      return "?";
    }
    
    typedef enum tCallConv
    {
      CallConvCdecl,    // Params on stack; caller removes params
      CallConvStdCall,  // Params on stack; callee removes params
      CallConvFastCall  // Params in ECX, EDX and on stack; callee removes params
    } tCallConv;
    
    DWORD Execute32bitFunctionFromExe(PCSTR ExeName,
                                      int FunctionAddressIsRelative,
                                      DWORD FunctionAddress,
                                      tCallConv CallConvention,
                                      DWORD CodeDataStackSize,
                                      ULONG64* ResultEdxEax,
                                      DWORD DwordParamsCount,
                                      .../* DWORD params */)
    {
      STARTUPINFO startupInfo;
      PROCESS_INFORMATION processInfo;
      DWORD dwContinueStatus = DBG_CONTINUE; // exception continuation
      DEBUG_EVENT dbgEvt;
      UCHAR* procMem = NULL;
      DWORD breakPointCount = 0;
      DWORD err = ERROR_SUCCESS;
      DWORD ecxEdxParams[2] = { 0, 0 };
      DWORD imageBase = 0;
      CONTEXT ctx;
      va_list ap;
    
      va_start(ap, DwordParamsCount);
    
      *ResultEdxEax = 0;
    
      memset(&startupInfo, 0, sizeof(startupInfo));
      startupInfo.cb = sizeof(startupInfo);
      memset(&processInfo, 0, sizeof(processInfo));
    
      if (!CreateProcess(
        NULL,
        (LPSTR)ExeName,
        NULL,
        NULL,
        FALSE,
        DEBUG_ONLY_THIS_PROCESS, // DEBUG_PROCESS,
        NULL,
        NULL,
        &startupInfo,
        &processInfo))
      {
        printf("CreateProcess() failed with error 0x%08X\n",
               err = GetLastError());
        goto Cleanup;
      }
    
      printf("Process 0x%08X (0x%08X) \"%s\" created,\n"
             "  Thread 0x%08X (0x%08X) created\n",
             processInfo.dwProcessId,
             processInfo.hProcess,
             ExeName,
             processInfo.dwThreadId,
             processInfo.hThread);
    
      procMem = VirtualAllocEx(
        processInfo.hProcess,
        NULL,
        CodeDataStackSize,
        MEM_COMMIT | MEM_RESERVE,
        PAGE_EXECUTE_READWRITE);
    
      if (procMem == NULL)
      {
        printf("VirtualAllocEx() failed with error 0x%08X\n",
               err = GetLastError());
        goto Cleanup;
      }
    
      printf("Allocated RWX memory in process 0x%08X (0x%08X) "
             "at address 0x%08X\n",
             processInfo.dwProcessId,
             processInfo.hProcess,
             procMem);
    
      while (dwContinueStatus)
      {
        // Wait for a debugging event to occur. The second parameter indicates
        // that the function does not return until a debugging event occurs.
        if (!WaitForDebugEvent(&dbgEvt, INFINITE))
        {
          printf("WaitForDebugEvent() failed with error 0x%08X\n",
                 err = GetLastError());
          goto Cleanup;
        }
    
        // Process the debugging event code.
        switch (dbgEvt.dwDebugEventCode)
        {
        case EXCEPTION_DEBUG_EVENT:
        // Process the exception code. When handling
        // exceptions, remember to set the continuation
        // status parameter (dwContinueStatus). This value
        // is used by the ContinueDebugEvent function.
    
          printf("%s (%s) Exception in process 0x%08X, thread 0x%08X\n"
                 "  Exc. Code = 0x%08X (%s), Instr. Address = 0x%08X",
                 dbgEvt.u.Exception.dwFirstChance ?
                   "First Chance" : "Last Chance",
                 dbgEvt.u.Exception.ExceptionRecord.ExceptionFlags ?
                   "non-continuable" : "continuable",
                 dbgEvt.dwProcessId,
                 dbgEvt.dwThreadId,
                 dbgEvt.u.Exception.ExceptionRecord.ExceptionCode,
                 GetExceptionName(dbgEvt.u.Exception.ExceptionRecord.ExceptionCode),
                 dbgEvt.u.Exception.ExceptionRecord.ExceptionAddress);
    
          if (dbgEvt.u.Exception.ExceptionRecord.ExceptionCode ==
              EXCEPTION_ACCESS_VIOLATION)
          {
            ULONG_PTR* info = dbgEvt.u.Exception.ExceptionRecord.ExceptionInformation;
            printf(",\n  Access Address = 0x%08X, Access = 0x%08X (%s)",
                   (DWORD)info[1],
                   (DWORD)info[0],
                   (info[0] == 0) ?
                     "read" : ((info[0] == 1) ? "write" : "execute")); // 8 = DEP
          }
    
          printf("\n");
    
          // Get the thread context (register state).
          // We'll need to either display it (in case of unexpected exceptions) or
          // modify it (to execute our code) or read it (to get the results of
          // execution).
          memset(&ctx, 0, sizeof(ctx));
          ctx.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL;
          if (!GetThreadContext(processInfo.hThread, &ctx))
          {
            printf("GetThreadContext() failed with error 0x%08X\n",
                   err = GetLastError());
            goto Cleanup;
          }
    
    #if 0
          printf("  EAX=0x%08X EBX=0x%08X ECX=0x%08X EDX=0x%08X EFLAGS=0x%08X\n"
                 "  ESI=0x%08X EDI=0x%08X EBP=0x%08X ESP=0x%08X EIP=0x%08X\n",
                 ctx.Eax, ctx.Ebx, ctx.Ecx, ctx.Edx, ctx.EFlags, 
                 ctx.Esi, ctx.Edi, ctx.Ebp, ctx.Esp, ctx.Eip);
    #endif
    
          if (dbgEvt.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT &&
              breakPointCount == 0)
          {
            // Update the context so our code can be executed
            DWORD mem, i, data;
            SIZE_T numberOfBytesCopied;
    
            mem = (DWORD)procMem + CodeDataStackSize;
    
            // Child process memory layout (inside the procMem[] buffer):
            //
            //    higher
            //  addresses
            //      .
            //      .     UD2 instruction (causes #UD, indicator of successful
            //      .     completion of FunctionAddress())
            //      .
            //      .     last on-stack parameter for FunctionAddress()
            //      .     ...
            //      .     first on-stack parameter for FunctionAddress()
            //      .
            //      .     address of UD2 instruction (as if "call FunctionAddress"
            //      .     executed just before it and is going to return to UD2)
            //      .     (ESP will point here)
            //      .
            //      .     FunctionAddress()'s stack
            //      .
            //    lower
            //  addresses
    
            mem -= 2;
            data = 0x0B0F; // 0x0F, 0x0B = UD2 instruction
            if (!WriteProcessMemory(processInfo.hProcess,
                                    (PVOID)mem,
                                    &data,
                                    2,
                                    &numberOfBytesCopied))
            {
    ErrWriteMem1:
              printf("WriteProcessMemory() failed with error 0x%08X\n",
                     err = GetLastError());
              goto Cleanup;
            }
            else if (numberOfBytesCopied != 2)
            {
    ErrWriteMem2:
              printf("WriteProcessMemory() failed with error 0x%08X\n",
                     err = ERROR_BAD_LENGTH);
              goto Cleanup;
            }
    
            // Copy function parameters.
    
            mem &= 0xFFFFFFFC; // align the address for the stack
    
            for (i = 0; i < DwordParamsCount; i++)
            {
              if (CallConvention == CallConvFastCall && i < 2)
              {
                ecxEdxParams[i] = va_arg(ap, DWORD);
              }
              else
              {
                data = va_arg(ap, DWORD);
                if (!WriteProcessMemory(processInfo.hProcess,
                                        (DWORD*)mem - DwordParamsCount + i,
                                        &data,
                                        sizeof(data),
                                        &numberOfBytesCopied))
                {
                  goto ErrWriteMem1;
                }
                else if (numberOfBytesCopied != sizeof(data))
                {
                  goto ErrWriteMem2;
                }
              }
            }
    
            // Adjust what will become ESP according to the number of on-stack parameters.
            for (i = 0; i < DwordParamsCount; i++)
            {
              if (CallConvention != CallConvFastCall || i >= 2)
              {
                mem -= 4;
              }
            }
    
            // Store the function return address.
            mem -= 4;
            data = (DWORD)procMem + CodeDataStackSize - 2; // address of UD2
            if (!WriteProcessMemory(processInfo.hProcess,
                                    (PVOID)mem,
                                    &data,
                                    sizeof(data),
                                    &numberOfBytesCopied))
            {
              goto ErrWriteMem1;
            }
            else if (numberOfBytesCopied != sizeof(data))
            {
              goto ErrWriteMem2;
            }
    
            // Last-minute preparations for execution...
            // Set up the registers (ECX, EDX, EFLAGS, EIP, ESP).
    
            if (CallConvention == CallConvFastCall)
            {
              if (DwordParamsCount >= 1) ctx.Ecx = ecxEdxParams[0];
              if (DwordParamsCount >= 2) ctx.Edx = ecxEdxParams[1];
            }
    
            ctx.EFlags &= ~(1 << 10); // clear DF for string instructions
            ctx.Eip = FunctionAddress + imageBase * !!FunctionAddressIsRelative;
            ctx.Esp = mem;
    
            if (!SetThreadContext(processInfo.hThread, &ctx))
            {
              printf("SetThreadContext() failed with error 0x%08X\n",
                     err = GetLastError());
              goto Cleanup;
            }
    
            printf("Copied code/data to the process\n");
    
    #if 0
            for (i = esp; i < (DWORD)procMem + CodeDataStackSize; i++)
            {
              data = 0;
              ReadProcessMemory(processInfo.hProcess,
                                (void*)i,
                                &data,
                                1,
                                &numberOfBytesCopied);
              printf("E[SI]P = 0x%08X: 0x%02X\n", i, data);
            }
    #endif
    
            breakPointCount++;
            dwContinueStatus = DBG_CONTINUE; // continue execution of our code
          }
          else if (dbgEvt.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_ILLEGAL_INSTRUCTION &&
                   breakPointCount == 1 &&
                   ctx.Eip == (DWORD)procMem + CodeDataStackSize - 2/*UD2 size*/)
          {
            // The code has finished execution as expected.
            // Collect the results.
    
            *ResultEdxEax = ((ULONG64)ctx.Edx << 32) | ctx.Eax;
    
            printf("Copied code/data from the process\n");
    
            dwContinueStatus = 0; // stop debugging
          }
          else
          {
            // Unexpected event. Do not continue execution.
    
            printf("  EAX=0x%08X EBX=0x%08X ECX=0x%08X EDX=0x%08X EFLAGS=0x%08X\n"
                   "  ESI=0x%08X EDI=0x%08X EBP=0x%08X ESP=0x%08X EIP=0x%08X\n",
                   ctx.Eax, ctx.Ebx, ctx.Ecx, ctx.Edx, ctx.EFlags, 
                   ctx.Esi, ctx.Edi, ctx.Ebp, ctx.Esp, ctx.Eip);
    
            err = dbgEvt.u.Exception.ExceptionRecord.ExceptionCode;
            goto Cleanup;
          }
          break; // case EXCEPTION_DEBUG_EVENT:
    
        case CREATE_PROCESS_DEBUG_EVENT:
        // As needed, examine or change the registers of the
        // process's initial thread with the GetThreadContext and
        // SetThreadContext functions; read from and write to the
        // process's virtual memory with the ReadProcessMemory and
        // WriteProcessMemory functions; and suspend and resume
        // thread execution with the SuspendThread and ResumeThread
        // functions. Be sure to close the handle to the process image
        // file with CloseHandle.
          printf("Process 0x%08X (0x%08X) "
                 "created, base = 0x%08X,\n"
                 "  Thread 0x%08X (0x%08X) created, start = 0x%08X\n",
                 dbgEvt.dwProcessId,
                 dbgEvt.u.CreateProcessInfo.hProcess,
                 dbgEvt.u.CreateProcessInfo.lpBaseOfImage,
                 dbgEvt.dwThreadId,
                 dbgEvt.u.CreateProcessInfo.hThread,
                 dbgEvt.u.CreateProcessInfo.lpStartAddress);
          // Found image base!
          imageBase = (DWORD)dbgEvt.u.CreateProcessInfo.lpBaseOfImage;
          dwContinueStatus = DBG_CONTINUE;
          break;
    
        case EXIT_PROCESS_DEBUG_EVENT:
        // Display the process's exit code.
          printf("Process 0x%08X exited, exit code = 0x%08X\n",
                 dbgEvt.dwProcessId,
                 dbgEvt.u.ExitProcess.dwExitCode);
          // Unexpected event. Do not continue execution.
          err = ERROR_PROC_NOT_FOUND;
          goto Cleanup;
    
        case CREATE_THREAD_DEBUG_EVENT:
        case EXIT_THREAD_DEBUG_EVENT:
        case LOAD_DLL_DEBUG_EVENT:
        case UNLOAD_DLL_DEBUG_EVENT:
        case OUTPUT_DEBUG_STRING_EVENT:
          dwContinueStatus = DBG_CONTINUE;
          break;
    
        case RIP_EVENT:
          printf("RIP: Error = 0x%08X, Type = 0x%08X\n",
                 dbgEvt.u.RipInfo.dwError,
                 dbgEvt.u.RipInfo.dwType);
          // Unexpected event. Do not continue execution.
          err = dbgEvt.u.RipInfo.dwError;
          goto Cleanup;
        } // end of switch (dbgEvt.dwDebugEventCode)
    
        // Resume executing the thread that reported the debugging event.
        if (dwContinueStatus)
        {
          if (!ContinueDebugEvent(dbgEvt.dwProcessId,
                                  dbgEvt.dwThreadId,
                                  dwContinueStatus))
          {
            printf("ContinueDebugEvent() failed with error 0x%08X\n",
                   err = GetLastError());
            goto Cleanup;
          }
        }
      } // end of while (dwContinueStatus)
    
      err = ERROR_SUCCESS;
    
    Cleanup:
    
      if (processInfo.hProcess != NULL)
      {
        if (procMem != NULL)
        {
          VirtualFreeEx(processInfo.hProcess, procMem, 0, MEM_RELEASE);
        }
        TerminateProcess(processInfo.hProcess, 0);
        CloseHandle(processInfo.hThread);
        CloseHandle(processInfo.hProcess);
      }
    
      va_end(ap);
    
      return err;
    }
    
    int __cdecl FunctionCdecl(int x, int y, int z)
    {
      return x + y + z;
    }
    
    int __stdcall FunctionStdCall(int x, int y, int z)
    {
      return x * y * z;
    }
    
    ULONG64 __fastcall FunctionFastCall(DWORD x, DWORD y, DWORD z)
    {
      return (ULONG64)x * y + z;
    }
    
    int main(int argc, char** argv)
    {
      DWORD err;
      ULONG64 resultEdxEax;
    
      err = Execute32bitFunctionFromExe(argv[0]/*ExeName*/,
                                        1/*FunctionAddressIsRelative*/,
                                        (DWORD)&FunctionCdecl -
                                          (DWORD)GetModuleHandle(NULL),
                                        CallConvCdecl,
                                        4096/*CodeDataStackSize*/,
                                        &resultEdxEax,
                                        3/*DwordParamsCount*/,
                                        2, 3, 4);
      if (err == ERROR_SUCCESS)
        printf("2 + 3 + 4 = %d\n", (int)resultEdxEax);
    
      err = Execute32bitFunctionFromExe(argv[0]/*ExeName*/,
                                        1/*FunctionAddressIsRelative*/,
                                        (DWORD)&FunctionStdCall -
                                          (DWORD)GetModuleHandle(NULL),
                                        CallConvStdCall,
                                        4096/*CodeDataStackSize*/,
                                        &resultEdxEax,
                                        3/*DwordParamsCount*/,
                                        -2, 3, 4);
      if (err == ERROR_SUCCESS)
        printf("-2 * 3 * 4 = %d\n", (int)resultEdxEax);
    
      err = Execute32bitFunctionFromExe(argv[0]/*ExeName*/,
                                        1/*FunctionAddressIsRelative*/,
                                        (DWORD)&FunctionFastCall -
                                          (DWORD)GetModuleHandle(NULL),
                                        CallConvFastCall,
                                        4096/*CodeDataStackSize*/,
                                        &resultEdxEax,
                                        3/*DwordParamsCount*/,
                                        -1, -1, -1);
      if (err == ERROR_SUCCESS)
        printf("0xFFFFFFFF * 0xFFFFFFFF + 0xFFFFFFFF = 0x%llX\n",
               (unsigned long long)resultEdxEax);
    
      return 0;
    }
    

    输出:

    Process 0x00001514 (0x00000040) "C:\MinGW\msys\1.0\home\Alex\unexported.exe" cre
    ated,
      Thread 0x00000CB0 (0x0000003C) created
    Allocated RWX memory in process 0x00001514 (0x00000040) at address 0x002B0000
    Process 0x00001514 (0x00000044) created, base = 0x00400000,
      Thread 0x00000CB0 (0x00000048) created, start = 0x0040126C
    First Chance (continuable) Exception in process 0x00001514, thread 0x00000CB0
      Exc. Code = 0x80000003 (EXCEPTION_BREAKPOINT), Instr. Address = 0x77090FAB
    Copied code/data to the process
    First Chance (continuable) Exception in process 0x00001514, thread 0x00000CB0
      Exc. Code = 0xC000001D (EXCEPTION_ILLEGAL_INSTRUCTION), Instr. Address = 0x002
    B0FFE
    Copied code/data from the process
    2 + 3 + 4 = 9
    Process 0x00001828 (0x0000003C) "C:\MinGW\msys\1.0\home\Alex\unexported.exe" cre
    ated,
      Thread 0x00001690 (0x00000040) created
    Allocated RWX memory in process 0x00001828 (0x0000003C) at address 0x002B0000
    Process 0x00001828 (0x0000006C) created, base = 0x00400000,
      Thread 0x00001690 (0x00000074) created, start = 0x0040126C
    First Chance (continuable) Exception in process 0x00001828, thread 0x00001690
      Exc. Code = 0x80000003 (EXCEPTION_BREAKPOINT), Instr. Address = 0x77090FAB
    Copied code/data to the process
    First Chance (continuable) Exception in process 0x00001828, thread 0x00001690
      Exc. Code = 0xC000001D (EXCEPTION_ILLEGAL_INSTRUCTION), Instr. Address = 0x002
    B0FFE
    Copied code/data from the process
    -2 * 3 * 4 = -24
    Process 0x00001388 (0x00000040) "C:\MinGW\msys\1.0\home\Alex\unexported.exe" cre
    ated,
      Thread 0x00001098 (0x0000003C) created
    Allocated RWX memory in process 0x00001388 (0x00000040) at address 0x002B0000
    Process 0x00001388 (0x0000008C) created, base = 0x00400000,
      Thread 0x00001098 (0x00000090) created, start = 0x0040126C
    First Chance (continuable) Exception in process 0x00001388, thread 0x00001098
      Exc. Code = 0x80000003 (EXCEPTION_BREAKPOINT), Instr. Address = 0x77090FAB
    Copied code/data to the process
    First Chance (continuable) Exception in process 0x00001388, thread 0x00001098
      Exc. Code = 0xC000001D (EXCEPTION_ILLEGAL_INSTRUCTION), Instr. Address = 0x002
    B0FFE
    Copied code/data from the process
    0xFFFFFFFF * 0xFFFFFFFF + 0xFFFFFFFF = 0xFFFFFFFF00000000
    

答案 2 :(得分:2)

不是将EXE加载到您的流程中,而是采用两种更好的(IMO)方式:

1)使用调试API(或PyDbg之类的东西)在调试器下启动目标,然后在堆栈中设置参数,将EIP设置为必要的地址,在返回地址上放置断点,然后继续。

2)用一些IPC制作一个小DLL与你的程序进行通信,将它注入目标(有几种方法可以做到,最简单的可能是键盘挂钩)并让它调用必要的代码。或者你也可以使用现有技术,例如Intel's PIN