| /* ********************************************************** |
| * Copyright (c) 2005-2006 VMware, Inc. All rights reserved. |
| * **********************************************************/ |
| |
| /* |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * |
| * * Redistributions of source code must retain the above copyright notice, |
| * this list of conditions and the following disclaimer. |
| * |
| * * Redistributions in binary form must reproduce the above copyright notice, |
| * this list of conditions and the following disclaimer in the documentation |
| * and/or other materials provided with the distribution. |
| * |
| * * Neither the name of VMware, Inc. nor the names of its contributors may be |
| * used to endorse or promote products derived from this software without |
| * specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| * ARE DISCLAIMED. IN NO EVENT SHALL VMWARE, INC. OR CONTRIBUTORS BE LIABLE |
| * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
| * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
| * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
| * DAMAGE. |
| */ |
| |
| /* DR core / shared library interface unit tests */ |
| /* executed as part of the unit tests for processes.c */ |
| |
| /* need to have a core build anyway for these tests to work */ |
| #include "win32/events.h" |
| |
| /* nudge tends to hang/timeout if you nudge right after the |
| * process starts. so in order to let the basic tests pass, |
| * they all sleep for at least this long before trying to |
| * nudge. |
| * of course this should be fixed and then we should create |
| * stress tests to address this specifically. */ |
| #define NUDGE_LET_PROCESS_START_WAIT 500 |
| |
| #define TEST_TIMEOUT 2000 |
| #define LAUNCH_TIMEOUT 1000 |
| |
| #define WAIT_FOR_APP(hProc) \ |
| DO_ASSERT(WAIT_OBJECT_0 == WaitForSingleObject(hProc, TEST_TIMEOUT * 2)) |
| |
| #define LONG_WAIT_FOR_APP(hProc) \ |
| DO_ASSERT(WAIT_OBJECT_0 == WaitForSingleObject(hProc, TEST_TIMEOUT * 20)) |
| |
| #define DO_TEST(name, appstr, block) DO_TEST_HP(name, appstr, TRUE, block) |
| |
| #define TESTER_1_BLOCK \ |
| "BEGIN_BLOCK\n" \ |
| "APP_NAME=tester_1.exe\n" \ |
| "DYNAMORIO_OPTIONS=-kill_thread -kill_thread_max 1000 -report_max 0 -dumpcore_mask " \ |
| "0xff\n" \ |
| "END_BLOCK\n" |
| |
| #define TESTER_2_BLOCK \ |
| "BEGIN_BLOCK\n" \ |
| "APP_NAME=tester_2.exe\n" \ |
| "DYNAMORIO_OPTIONS=-dumpcore_mask 0xff\n" \ |
| "END_BLOCK\n" |
| |
| #define TESTER_1_HOT_PATCH_BLOCK \ |
| "BEGIN_BLOCK\n" \ |
| "APP_NAME=tester_1.exe\n" \ |
| "DYNAMORIO_OPTIONS=-kill_thread -dumpcore_mask 0xff\n" \ |
| "DYNAMORIO_HOT_PATCH_MODES=\\conf\\test-modes.cfg\n" \ |
| "BEGIN_MP_MODES\n" \ |
| "1\n" \ |
| "TEST.000A:2\n" \ |
| "END_MP_MODES\n" \ |
| "END_BLOCK\n" |
| |
| #define TESTER_1_HOT_PATCH_DETECT_BLOCK \ |
| "BEGIN_BLOCK\n" \ |
| "APP_NAME=tester_1.exe\n" \ |
| "DYNAMORIO_OPTIONS=-kill_thread -dumpcore_mask 0xff\n" \ |
| "DYNAMORIO_HOT_PATCH_MODES=\\conf\\test-modes.cfg\n" \ |
| "BEGIN_MP_MODES\n" \ |
| "1\n" \ |
| "TEST.000A:1\n" \ |
| "END_MP_MODES\n" \ |
| "END_BLOCK\n" |
| |
| /* simple detach */ |
| DO_TEST(detach, TESTER_1_BLOCK, { |
| UINT pid; |
| LAUNCH_APP(L"tester_1.exe 5000", &pid); |
| /* FIXME: if this isn't here, the first run (right after |
| * building the tests) always fails. */ |
| Sleep(LAUNCH_TIMEOUT * 2); |
| VERIFY_UNDER_DR(pid); |
| CHECKED_OPERATION(detach(pid, TRUE, DETACH_RECOMMENDED_TIMEOUT)); |
| VERIFY_NOT_UNDER_DR(pid); |
| TERMINATE_PROCESS(pid); |
| }); |
| |
| /* pending restart */ |
| DO_TEST(pending_restart, TESTER_1_BLOCK, { |
| UINT pid; |
| LAUNCH_APP(L"tester_1.exe 5000", &pid); |
| Sleep(LAUNCH_TIMEOUT); |
| VERIFY_UNDER_DR(pid); |
| CHECKED_OPERATION(detach(pid, TRUE, DETACH_RECOMMENDED_TIMEOUT)); |
| VERIFY_NOT_UNDER_DR(pid); |
| DO_ASSERT(is_process_pending_restart(pid)); |
| DO_ASSERT(is_any_process_pending_restart()); |
| TERMINATE_PROCESS(pid); |
| }); |
| |
| /* detach_exe */ |
| DO_TEST(detach_exe, TESTER_1_BLOCK TESTER_2_BLOCK, { |
| UINT pid1; |
| UINT pid2; |
| UINT pid3; |
| LAUNCH_APP(L"tester_1.exe", &pid1); |
| LAUNCH_APP(L"tester_2.exe", &pid2); |
| LAUNCH_APP(L"tester_1.exe", &pid3); |
| Sleep(LAUNCH_TIMEOUT); |
| VERIFY_UNDER_DR(pid1); |
| VERIFY_UNDER_DR(pid2); |
| VERIFY_UNDER_DR(pid3); |
| CHECKED_OPERATION(detach_exe(L"tester_1.exe", DETACH_RECOMMENDED_TIMEOUT)); |
| VERIFY_NOT_UNDER_DR(pid1); |
| VERIFY_UNDER_DR(pid2); |
| VERIFY_NOT_UNDER_DR(pid3); |
| DO_ASSERT(is_process_pending_restart(pid1)); |
| DO_ASSERT(!is_process_pending_restart(pid2)); |
| DO_ASSERT(is_any_process_pending_restart()); |
| TERMINATE_PROCESS(pid1); |
| TERMINATE_PROCESS(pid2); |
| TERMINATE_PROCESS(pid3); |
| }); |
| |
| /* detach_all */ |
| DO_TEST(detach_all, TESTER_1_BLOCK TESTER_2_BLOCK, { |
| UINT pid1; |
| UINT pid2; |
| UINT pid3; |
| LAUNCH_APP(L"tester_1.exe", &pid1); |
| LAUNCH_APP(L"tester_2.exe", &pid2); |
| LAUNCH_APP(L"tester_1.exe", &pid3); |
| Sleep(LAUNCH_TIMEOUT); |
| VERIFY_UNDER_DR(pid1); |
| VERIFY_UNDER_DR(pid2); |
| VERIFY_UNDER_DR(pid3); |
| CHECKED_OPERATION(detach_all(DETACH_RECOMMENDED_TIMEOUT)); |
| VERIFY_NOT_UNDER_DR(pid1); |
| VERIFY_NOT_UNDER_DR(pid2); |
| VERIFY_NOT_UNDER_DR(pid3); |
| DO_ASSERT(is_process_pending_restart(pid1)); |
| DO_ASSERT(is_any_process_pending_restart()); |
| TERMINATE_PROCESS(pid1); |
| TERMINATE_PROCESS(pid2); |
| TERMINATE_PROCESS(pid3); |
| }); |
| |
| /* consistency_detach */ |
| DO_TEST(consistency_detach, TESTER_1_BLOCK TESTER_2_BLOCK, { |
| UINT pid1; |
| UINT pid2; |
| UINT pid3; |
| LAUNCH_APP(L"tester_1.exe", &pid1); |
| LAUNCH_APP(L"tester_2.exe", &pid2); |
| LAUNCH_APP(L"tester_1.exe", &pid3); |
| Sleep(LAUNCH_TIMEOUT); |
| VERIFY_UNDER_DR(pid1); |
| VERIFY_UNDER_DR(pid2); |
| VERIFY_UNDER_DR(pid3); |
| CHECKED_OPERATION(load_test_config(TESTER_2_BLOCK, FALSE)); |
| CHECKED_OPERATION(consistency_detach(DETACH_RECOMMENDED_TIMEOUT)); |
| VERIFY_NOT_UNDER_DR(pid1); |
| VERIFY_UNDER_DR(pid2); |
| VERIFY_NOT_UNDER_DR(pid3); |
| TERMINATE_PROCESS(pid1); |
| TERMINATE_PROCESS(pid2); |
| TERMINATE_PROCESS(pid3); |
| }); |
| |
| /* check start/stop events */ |
| DO_TEST(start_stop_event, TESTER_1_BLOCK, { |
| UINT pid; |
| HANDLE hProc; |
| LAUNCH_APP_HANDLE(L"tester_1.exe 10", &pid, &hProc); |
| WAIT_FOR_APP(hProc); |
| DO_ASSERT( |
| check_for_event(MSG_INFO_PROCESS_START, L"tester_1.exe", pid, NULL, NULL, 0)); |
| DO_ASSERT( |
| check_for_event(MSG_INFO_PROCESS_STOP, L"tester_1.exe", pid, NULL, NULL, 0)); |
| }); |
| |
| /* check detach event */ |
| DO_TEST(detach_event, TESTER_1_BLOCK, { |
| UINT pid; |
| LAUNCH_APP(L"tester_1.exe 2000", &pid); |
| Sleep(LAUNCH_TIMEOUT); |
| VERIFY_UNDER_DR(pid); |
| CHECKED_OPERATION(detach(pid, TRUE, DETACH_RECOMMENDED_TIMEOUT)); |
| VERIFY_NOT_UNDER_DR(pid); |
| Sleep(100); |
| DO_ASSERT( |
| check_for_event(MSG_INFO_PROCESS_START, L"tester_1.exe", pid, NULL, NULL, 0)); |
| DO_ASSERT(check_for_event(MSG_INFO_DETACHING, L"tester_1.exe", pid, NULL, NULL, 0)); |
| TERMINATE_PROCESS(pid); |
| }); |
| |
| /* check attack event */ |
| DO_TEST(attack_event, TESTER_1_BLOCK, { |
| UINT pid; |
| HANDLE hProc; |
| WCHAR s3[MAX_PATH]; |
| WCHAR s4[MAX_PATH]; |
| LAUNCH_APP_HANDLE(L"tester_1.exe 10 10 1", &pid, &hProc); |
| WAIT_FOR_APP(hProc); |
| DO_ASSERT(check_for_event(MSG_SEC_VIOLATION_THREAD, L"tester_1.exe", pid, s3, s4, |
| MAX_PATH)); |
| /* make sure threat id looks ok */ |
| DO_ASSERT(11 == wcslen(s3)); |
| }); |
| |
| /* check forensics event/file */ |
| DO_TEST(forensics_file, TESTER_1_BLOCK, { |
| UINT pid; |
| HANDLE hProc; |
| WCHAR s3[MAX_PATH]; |
| WCHAR s4[MAX_PATH]; |
| LAUNCH_APP_HANDLE(L"tester_1.exe 10 10 1", &pid, &hProc); |
| WAIT_FOR_APP(hProc); |
| DO_ASSERT( |
| check_for_event(MSG_SEC_VIOLATION_THREAD, L"tester_1.exe", pid, NULL, NULL, 0)); |
| DO_ASSERT(check_for_event(MSG_SEC_FORENSICS, L"tester_1.exe", pid, s3, s4, MAX_PATH)); |
| DO_ASSERT(file_exists(s3)); |
| }); |
| |
| /* stress forensics event/file */ |
| DO_TEST(forensics_stress, TESTER_1_BLOCK, { |
| UINT pid; |
| HANDLE hProc; |
| WCHAR s3[MAX_PATH]; |
| WCHAR s4[MAX_PATH]; |
| int i; |
| LAUNCH_APP_HANDLE(L"tester_1.exe 10 10 0 100", &pid, &hProc); |
| LONG_WAIT_FOR_APP(hProc); |
| for (i = 0; i < 100; i++) { |
| DO_ASSERT(check_for_event(MSG_SEC_VIOLATION_THREAD, L"tester_1.exe", pid, NULL, |
| NULL, 0)); |
| DO_ASSERT( |
| check_for_event(MSG_SEC_FORENSICS, L"tester_1.exe", pid, s3, s4, MAX_PATH)); |
| DO_ASSERT(file_exists(s3)); |
| } |
| DO_ASSERT( |
| check_for_event(MSG_INFO_PROCESS_STOP, L"tester_1.exe", pid, NULL, NULL, 0)); |
| }); |
| |
| /* check to make sure nudge doesn't leave the code lying around */ |
| DO_TEST(check_nudge, TESTER_1_BLOCK, { |
| UINT pid; |
| WCHAR nudge_code_buf[MAX_PATH]; |
| |
| LAUNCH_APP(L"tester_1.exe", &pid); |
| Sleep(LAUNCH_TIMEOUT); |
| VERIFY_UNDER_DR(pid); |
| Sleep(NUDGE_LET_PROCESS_START_WAIT); |
| CHECKED_OPERATION(hotp_notify_modes_update(pid, TRUE, TEST_TIMEOUT)); |
| DO_ASSERT(ERROR_SUCCESS != |
| get_config_parameter(L_PRODUCT_NAME, FALSE, L_DYNAMORIO_VAR_NUDGE, |
| nudge_code_buf, MAX_PATH)); |
| TERMINATE_PROCESS(pid); |
| }); |
| |
| /* simple test for hotpatching */ |
| DO_TEST(hotp_protect, TESTER_1_HOT_PATCH_BLOCK, { |
| UINT pid; |
| char fc[MAX_PATH]; |
| LAUNCH_APP_AND_WAIT(L"tester_1.exe 100", &pid); |
| CHECKED_OPERATION(read_file_contents(L"tester.out", fc, MAX_PATH, NULL)); |
| DO_ASSERT(0 == strncmp(fc, "10", 2)); |
| }); |
| |
| /* detect should report 00 */ |
| DO_TEST(hotp_detect, TESTER_1_HOT_PATCH_DETECT_BLOCK, { |
| UINT pid; |
| char fc[MAX_PATH]; |
| LAUNCH_APP_AND_WAIT(L"tester_1.exe 100", &pid); |
| CHECKED_OPERATION(read_file_contents(L"tester.out", fc, MAX_PATH, NULL)); |
| DO_ASSERT(0 == strncmp(fc, "00", 2)); |
| }); |
| |
| /* basic nudge test */ |
| DO_TEST_HP(hotp_defs_nudge, TESTER_1_BLOCK, FALSE, /* don't load the modes file! */ |
| { |
| UINT pid; |
| char fc[MAX_PATH]; |
| HANDLE hProc; |
| hotp_policy_status_table_t *status_table = NULL; |
| |
| /* first launch app w/o hotpatch */ |
| LAUNCH_APP_AND_WAIT(L"tester_1.exe 10", &pid); |
| CHECKED_OPERATION(read_file_contents(L"tester.out", fc, MAX_PATH, NULL)); |
| DO_ASSERT(0 == strncmp(fc, "00", 2)); |
| |
| /* now, same thing with longer wait */ |
| LAUNCH_APP_HANDLE(L"tester_1.exe 2000", &pid, &hProc); |
| Sleep(LAUNCH_TIMEOUT); |
| VERIFY_UNDER_DR(pid); |
| |
| /* make sure nothing's there */ |
| DO_ASSERT(ERROR_DRMARKER_ERROR == get_hotp_status(pid, &status_table)); |
| |
| /* load the new config -- this time with hot patching*/ |
| CHECKED_OPERATION(load_test_config(TESTER_1_HOT_PATCH_BLOCK, TRUE)); |
| |
| /* and nudge */ |
| Sleep(NUDGE_LET_PROCESS_START_WAIT); |
| CHECKED_OPERATION(hotp_notify_defs_update(pid, TRUE, TEST_TIMEOUT)); |
| VERIFY_UNDER_DR(pid); |
| WAIT_FOR_APP(hProc); |
| |
| CHECKED_OPERATION(read_file_contents(L"tester.out", fc, MAX_PATH, NULL)); |
| DO_ASSERT(0 == strncmp(fc, "10", 2)); |
| }); |
| |
| DO_TEST(hotp_modes_nudge, TESTER_1_HOT_PATCH_BLOCK, { |
| UINT pid; |
| char fc[MAX_PATH]; |
| HANDLE hProc; |
| |
| /* first launch app w/hotpatch protect */ |
| LAUNCH_APP_AND_WAIT(L"tester_1.exe 10", &pid); |
| CHECKED_OPERATION(read_file_contents(L"tester.out", fc, MAX_PATH, NULL)); |
| DO_ASSERT(0 == strncmp(fc, "10", 2)); |
| |
| /* now, same thing with longer wait */ |
| LAUNCH_APP_HANDLE(L"tester_1.exe 2000", &pid, &hProc); |
| Sleep(LAUNCH_TIMEOUT); |
| VERIFY_UNDER_DR(pid); |
| |
| /* load the new config */ |
| CHECKED_OPERATION(load_test_config(TESTER_1_HOT_PATCH_DETECT_BLOCK, TRUE)); |
| |
| /* and do a modes nudge */ |
| Sleep(NUDGE_LET_PROCESS_START_WAIT); |
| CHECKED_OPERATION(hotp_notify_modes_update(pid, TRUE, TEST_TIMEOUT)); |
| VERIFY_UNDER_DR(pid); |
| WAIT_FOR_APP(hProc); |
| |
| CHECKED_OPERATION(read_file_contents(L"tester.out", fc, MAX_PATH, NULL)); |
| DO_ASSERT(0 == strncmp(fc, "00", 2)); |
| }); |
| |
| /* nudge twice to make sure we don't die */ |
| DO_TEST_HP(hotp_nudge_twice, TESTER_1_BLOCK, FALSE, { |
| UINT pid; |
| char fc[MAX_PATH]; |
| HANDLE hProc; |
| |
| /* first launch app w/o hotpatch */ |
| LAUNCH_APP_AND_WAIT(L"tester_1.exe 10", &pid); |
| CHECKED_OPERATION(read_file_contents(L"tester.out", fc, MAX_PATH, NULL)); |
| DO_ASSERT(0 == strncmp(fc, "00", 2)); |
| |
| LAUNCH_APP_HANDLE(L"tester_1.exe 2000", &pid, &hProc); |
| Sleep(LAUNCH_TIMEOUT); |
| VERIFY_UNDER_DR(pid); |
| |
| /* load the new config */ |
| CHECKED_OPERATION(load_test_config(TESTER_1_HOT_PATCH_BLOCK, TRUE)); |
| Sleep(NUDGE_LET_PROCESS_START_WAIT); |
| CHECKED_OPERATION(hotp_notify_defs_update(pid, TRUE, TEST_TIMEOUT)); |
| VERIFY_UNDER_DR(pid); |
| |
| /* load the old config back */ |
| CHECKED_OPERATION(load_test_config(TESTER_1_HOT_PATCH_DETECT_BLOCK, TRUE)); |
| CHECKED_OPERATION(hotp_notify_defs_update(pid, TRUE, TEST_TIMEOUT)); |
| VERIFY_UNDER_DR(pid); |
| WAIT_FOR_APP(hProc); |
| |
| CHECKED_OPERATION(read_file_contents(L"tester.out", fc, MAX_PATH, NULL)); |
| DO_ASSERT(0 == strncmp(fc, "00", 2)); |
| }); |
| |
| /* tests state of the patches */ |
| DO_TEST(hotp_protect_status, TESTER_1_HOT_PATCH_BLOCK, { |
| UINT pid; |
| HANDLE hProc; |
| hotp_policy_status_table_t *status_table = NULL; |
| |
| LAUNCH_APP_HANDLE(L"tester_1.exe 10 2500", &pid, &hProc); |
| Sleep(LAUNCH_TIMEOUT); |
| VERIFY_UNDER_DR(pid); |
| Sleep(500); |
| CHECKED_OPERATION(get_hotp_status(pid, &status_table)); |
| DO_ASSERT(status_table != NULL && status_table->num_policies > 0); |
| if (status_table != NULL && status_table->num_policies > 0) { |
| UINT j; |
| for (j = 0; j < status_table->num_policies; j++) { |
| if (0 == |
| strcmp(status_table->policy_status_array[j].policy_id, "TEST.000A") || |
| 0 == |
| strcmp(status_table->policy_status_array[j].policy_id, "TEST.000B")) { |
| DO_ASSERT(status_table->policy_status_array[j].inject_status == |
| HOTP_INJECT_PROTECT); |
| } |
| } |
| free_hotp_status_table(status_table); |
| } |
| WAIT_FOR_APP(hProc); |
| }); |
| |
| /* tests state of the patches */ |
| DO_TEST(hotp_pending_status, TESTER_1_HOT_PATCH_BLOCK, { |
| UINT pid; |
| HANDLE hProc; |
| hotp_policy_status_table_t *status_table = NULL; |
| |
| LAUNCH_APP_HANDLE(L"tester_1.exe 2500", &pid, &hProc); |
| Sleep(LAUNCH_TIMEOUT); |
| VERIFY_UNDER_DR(pid); |
| Sleep(200); |
| CHECKED_OPERATION(get_hotp_status(pid, &status_table)); |
| DO_ASSERT(status_table != NULL && status_table->num_policies > 0); |
| if (status_table != NULL && status_table->num_policies > 0) { |
| UINT j; |
| for (j = 0; j < status_table->num_policies; j++) { |
| if (0 == |
| strcmp(status_table->policy_status_array[j].policy_id, "TEST.000A") || |
| 0 == |
| strcmp(status_table->policy_status_array[j].policy_id, "TEST.000B")) { |
| DO_ASSERT(status_table->policy_status_array[j].inject_status == |
| HOTP_INJECT_PENDING); |
| } |
| } |
| free_hotp_status_table(status_table); |
| } |
| WAIT_FOR_APP(hProc); |
| }); |
| |
| /* sanity check to make sure we have different state */ |
| DO_TEST(hotp_detect_status, TESTER_1_HOT_PATCH_DETECT_BLOCK, { |
| UINT pid; |
| HANDLE hProc; |
| hotp_policy_status_table_t *status_table = NULL; |
| |
| LAUNCH_APP_HANDLE(L"tester_1.exe 10 2500", &pid, &hProc); |
| Sleep(LAUNCH_TIMEOUT); |
| VERIFY_UNDER_DR(pid); |
| Sleep(500); |
| CHECKED_OPERATION(get_hotp_status(pid, &status_table)); |
| DO_ASSERT(status_table != NULL && status_table->num_policies > 0); |
| if (status_table != NULL && status_table->num_policies > 0) { |
| UINT j; |
| for (j = 0; j < status_table->num_policies; j++) { |
| if (0 == |
| strcmp(status_table->policy_status_array[j].policy_id, "TEST.000A") || |
| 0 == |
| strcmp(status_table->policy_status_array[j].policy_id, "TEST.000B")) { |
| DO_ASSERT(status_table->policy_status_array[j].inject_status == |
| HOTP_INJECT_DETECT); |
| } |
| } |
| free_hotp_status_table(status_table); |
| } |
| WAIT_FOR_APP(hProc); |
| }); |
| |
| DO_TEST(hotp_modes_nudge_all, TESTER_1_HOT_PATCH_BLOCK, { |
| UINT pid; |
| char fc[MAX_PATH]; |
| HANDLE hProc; |
| |
| /* first launch app w/hotpatch protect */ |
| LAUNCH_APP_AND_WAIT(L"tester_1.exe 10", &pid); |
| CHECKED_OPERATION(read_file_contents(L"tester.out", fc, MAX_PATH, NULL)); |
| DO_ASSERT(0 == strncmp(fc, "10", 2)); |
| |
| /* now, same thing with longer wait */ |
| LAUNCH_APP_HANDLE(L"tester_1.exe 2000", &pid, &hProc); |
| Sleep(LAUNCH_TIMEOUT); |
| VERIFY_UNDER_DR(pid); |
| |
| /* load the new config */ |
| CHECKED_OPERATION(load_test_config(TESTER_1_HOT_PATCH_DETECT_BLOCK, TRUE)); |
| |
| /* and do a modes nudge */ |
| Sleep(NUDGE_LET_PROCESS_START_WAIT); |
| CHECKED_OPERATION(hotp_notify_all_modes_update(TEST_TIMEOUT)); |
| VERIFY_UNDER_DR(pid); |
| WAIT_FOR_APP(hProc); |
| |
| CHECKED_OPERATION(read_file_contents(L"tester.out", fc, MAX_PATH, NULL)); |
| DO_ASSERT(0 == strncmp(fc, "00", 2)); |
| }); |