Skip to content

Commit

Permalink
i#4990: Cross injection x64 to x86 failing (DynamoRIO#803)
Browse files Browse the repository at this point in the history
Fixes a small trouble cause by PR 4710 making syscall fails upon when running WoW64 process injected by x64 parent.
Also add a check for inject_x64 option cross-injection based on win32.xarch test.

Fixes: DynamoRIO#4990
  • Loading branch information
N0fix committed Aug 3, 2021
1 parent 2bc12c2 commit ffa309e
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 2 deletions.
3 changes: 2 additions & 1 deletion core/arch/mangle_shared.c
Original file line number Diff line number Diff line change
Expand Up @@ -1824,7 +1824,8 @@ find_syscall_num(dcontext_t *dcontext, instrlist_t *ilist, instr_t *instr)

if (prev == NULL) {
#if defined(WINDOWS) && defined(X64)
if (get_os_version() >= WINDOWS_VERSION_10_1511 && !DYNAMO_OPTION(inject_x64)) {
if (get_os_version() >= WINDOWS_VERSION_10_1511 &&
!DYNAMO_OPTION(inject_x64)) {
/* Handle the branch added in 1511 that isolates OP_syscall:
* 7ff9`13185630 4c8bd1 mov r10,rcx
* 7ff9`13185633 b843000000 mov eax,43h
Expand Down
2 changes: 1 addition & 1 deletion core/win32/inject.c
Original file line number Diff line number Diff line change
Expand Up @@ -1571,7 +1571,7 @@ inject_into_new_process(HANDLE phandle, HANDLE thandle, char *dynamo_path, bool
#endif
}
if (hook_location == 0) {
bool target_64 = !x86_code IF_X64(|| DYNAMO_OPTION(inject_x64));
bool target_64 = !x86_code;
uint64 ntdll_base = find_remote_ntdll_base(phandle, target_64);
uint64 thread_start =
get_remote_proc_address(phandle, ntdll_base, "RtlUserThreadStart");
Expand Down
65 changes: 65 additions & 0 deletions suite/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4511,6 +4511,71 @@ else (UNIX)
PASS_REGULAR_EXPRESSION ".*${expect}[ \n]*$")
endif (X86)


# Cross-arch injection x64 to x86 test using -inject_x64.
if(X64)
set(inject_x64_dir ${CMAKE_CURRENT_BINARY_DIR}/inject_x64)
set(test_bindir suite/tests/bin)
file(MAKE_DIRECTORY ${inject_x64_dir})
# Unfortunately, while CMake 3.13+ supports create_symlink on Windows, that
# only works if the user has the right privileges, so we can't set up
# lib dir symlinks like we do for unix cross-arch build-and-test.
# We have to make a copy in order to have parallel dirs with the two bitwidths.
file(MAKE_DIRECTORY "${inject_x64_dir}/${INSTALL_LIB}")
set(inject_x64_copy_stamp "${CMAKE_CURRENT_BINARY_DIR}/inject_64_copy.stamp")
add_custom_command(OUTPUT "${inject_x64_copy_stamp}"
DEPENDS dynamorio
COMMAND ${CMAKE_COMMAND} ARGS
-E touch "${inject_x64_copy_stamp}"
COMMAND ${CMAKE_COMMAND} ARGS
-E copy "${MAIN_LIBRARY_OUTPUT_DIRECTORY}/dynamorio.dll"
"${inject_x64_dir}/${INSTALL_LIB}/dynamorio.dll"
VERBATIM)
add_custom_target(inject_64_copy DEPENDS "${inject_x64_copy_stamp}")
add_dependencies(drcopy inject_64_copy)
# We use a client that takes some options and prints something at
# init and at exit to test cross-arch injection with clients.
get_target_path_for_execution(cur_client_path client.large_options.dll
"${location_suffix}")
set(xarch_client_path ${inject_x64_dir}/${test_bindir}/client.large_options.dll.dll)
get_target_path_for_execution(drrun_path drrun "${location_suffix}")
set(client64_path ${cur_client_path})
if (DEBUG)
set(config_type -DDEBUG=ON)
else ()
set(config_type "")
endif ()
# I abandoned --build-generator-platform (3.13+ only; VS gen only) or explicitly
# setting the full generator (fails w/ Ninja) and went with the env var scheme we
# use in our test suite.
_DR_set_VS_bitwidth_env_vars(${other_is64} env_names)
foreach (env ${env_names})
# Escape internal ; since this goes into a CMake "var=value;..." list.
string(REPLACE ";" "\\;" value "${${env}_env_value}")
list(APPEND test_env_pairs "${env}=${value}")
endforeach ()
add_test(win32.inject_x64 ${CMAKE_CTEST_COMMAND} -V
--build-and-test ${PROJECT_SOURCE_DIR} ${inject_x64_dir}
--build-generator ${CMAKE_GENERATOR}
--build-target dynamorio
--build-target common.eflags
--build-target client.large_options.dll
--build-noclean # Else it tries to clean between each target!
--build-makeprogram ${CMAKE_MAKE_PROGRAM}
--build-options ${config_type} -DBUILD_TESTS=ON -DBUILD_DOCS=OFF
-DBUILD_SAMPLES=OFF -DBUILD_EXT=OFF -DBUILD_CLIENTS=OFF
--test-command ${drrun_path} -dr_home ${inject_x64_dir} ${dr_test_ops}
-inject_x64
-c ${client64_path} -paramA foo -paramB bar --
${MAIN_RUNTIME_OUTPUT_DIRECTORY}/create_process.exe
${inject_x64_dir}/${test_bindir}/common.eflags.exe)
file(READ win32/inject_x64.templatex expect)
set_tests_properties(win32.inject_x64 PROPERTIES ENVIRONMENT
"${test_env_pairs}"
# We start with .* for all the config and build stuff.
PASS_REGULAR_EXPRESSION ".*${expect}[ \n]*$")
endif(X64)

# Cross-arch mixedmode/x86_to_x64 test: can only be done via a suite of tests that
# build both 32-bit and 64-bit. We have 32-bit just build, and
# 64-bit then builds and runs both directions.
Expand Down
19 changes: 19 additions & 0 deletions suite/tests/win32/inject_x64.templatex
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
large_options passed: -paramA foo -paramB bar
creating subprocess ".*inject_x64/suite/tests/bin/common.eflags.exe"
large_options passed: -paramA foo -paramB bar
OK 1 CF
OK 0 CF
OK 1 PF
OK 0 PF
OK 1 AF
OK 0 AF
OK 1 ZF
OK 0 ZF
OK 1 SF
OK 0 SF
OK 1 DF
OK 0 DF
OK 1 OF
OK 0 OF
parent done
large_options exiting

0 comments on commit ffa309e

Please sign in to comment.