mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-11 16:46:16 +00:00
Prepare unittest support
This commit is contained in:
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -15,3 +15,6 @@
|
|||||||
path = deps/mini-gdbstub
|
path = deps/mini-gdbstub
|
||||||
url = ../mini-gdbstub.git
|
url = ../mini-gdbstub.git
|
||||||
shallow = true
|
shallow = true
|
||||||
|
[submodule "deps/googletest"]
|
||||||
|
path = deps/googletest
|
||||||
|
url = https://github.com/google/googletest.git
|
||||||
|
|||||||
1
deps/CMakeLists.txt
vendored
1
deps/CMakeLists.txt
vendored
@@ -13,3 +13,4 @@ target_include_directories(reflect INTERFACE
|
|||||||
##########################################
|
##########################################
|
||||||
|
|
||||||
include(mini-gdbstub.cmake)
|
include(mini-gdbstub.cmake)
|
||||||
|
include(googletest.cmake)
|
||||||
1
deps/googletest
vendored
Submodule
1
deps/googletest
vendored
Submodule
Submodule deps/googletest added at df1544bcee
4
deps/googletest.cmake
vendored
Normal file
4
deps/googletest.cmake
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
option(BUILD_GMOCK OFF)
|
||||||
|
option(INSTALL_GTEST OFF)
|
||||||
|
|
||||||
|
add_subdirectory(googletest)
|
||||||
@@ -7,3 +7,4 @@ add_subdirectory(fuzzing-engine)
|
|||||||
add_subdirectory(fuzzer)
|
add_subdirectory(fuzzer)
|
||||||
add_subdirectory(bad-sample)
|
add_subdirectory(bad-sample)
|
||||||
add_subdirectory(test-sample)
|
add_subdirectory(test-sample)
|
||||||
|
add_subdirectory(windows-emulator-test)
|
||||||
|
|||||||
19
src/windows-emulator-test/CMakeLists.txt
Normal file
19
src/windows-emulator-test/CMakeLists.txt
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
file(GLOB_RECURSE SRC_FILES CONFIGURE_DEPENDS
|
||||||
|
*.cpp
|
||||||
|
*.hpp
|
||||||
|
*.rc
|
||||||
|
)
|
||||||
|
|
||||||
|
list(SORT SRC_FILES)
|
||||||
|
|
||||||
|
add_executable(windows-emulator-test ${SRC_FILES})
|
||||||
|
|
||||||
|
momo_assign_source_group(${SRC_FILES})
|
||||||
|
|
||||||
|
target_link_libraries(windows-emulator-test PRIVATE
|
||||||
|
gtest
|
||||||
|
common
|
||||||
|
windows-emulator
|
||||||
|
)
|
||||||
|
|
||||||
|
add_dependencies(windows-emulator-test test-sample)
|
||||||
27
src/windows-emulator-test/emulation_test.cpp
Normal file
27
src/windows-emulator-test/emulation_test.cpp
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <windows_emulator.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
namespace test
|
||||||
|
{
|
||||||
|
TEST(EmulationTest, BasicEmulationWorks)
|
||||||
|
{
|
||||||
|
windows_emulator emu{"./test-sample.exe"};
|
||||||
|
emu.logger.disable_output(true);
|
||||||
|
emu.start();
|
||||||
|
|
||||||
|
ASSERT_TRUE(emu.process().exit_status.has_value());
|
||||||
|
ASSERT_EQ(*emu.process().exit_status, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(EmulationTest, CountedEmulationWorks)
|
||||||
|
{
|
||||||
|
constexpr auto count = 123;
|
||||||
|
|
||||||
|
windows_emulator emu{ "./test-sample.exe" };
|
||||||
|
emu.logger.disable_output(true);
|
||||||
|
emu.start({}, count);
|
||||||
|
|
||||||
|
ASSERT_EQ(emu.process().executed_instructions, count);
|
||||||
|
}
|
||||||
|
}
|
||||||
7
src/windows-emulator-test/main.cpp
Normal file
7
src/windows-emulator-test/main.cpp
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
::testing::InitGoogleTest(&argc, argv);
|
||||||
|
return RUN_ALL_TESTS();
|
||||||
|
}
|
||||||
33
src/windows-emulator-test/serialization_test.cpp
Normal file
33
src/windows-emulator-test/serialization_test.cpp
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <windows_emulator.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
namespace test
|
||||||
|
{
|
||||||
|
TEST(SerializationTest, BasicSerializationWorks)
|
||||||
|
{
|
||||||
|
windows_emulator emu{"./test-sample.exe"};
|
||||||
|
emu.logger.disable_output(true);
|
||||||
|
emu.start({}, 100);
|
||||||
|
|
||||||
|
utils::buffer_serializer serializer{};
|
||||||
|
emu.serialize(serializer);
|
||||||
|
|
||||||
|
utils::buffer_deserializer deserializer{serializer.get_buffer()};
|
||||||
|
|
||||||
|
windows_emulator new_emu{};
|
||||||
|
new_emu.logger.disable_output(true);
|
||||||
|
new_emu.deserialize(deserializer);
|
||||||
|
|
||||||
|
new_emu.start();
|
||||||
|
emu.start();
|
||||||
|
|
||||||
|
utils::buffer_serializer serializer1{};
|
||||||
|
utils::buffer_serializer serializer2{};
|
||||||
|
|
||||||
|
emu.serialize(serializer1);
|
||||||
|
new_emu.serialize(serializer2);
|
||||||
|
|
||||||
|
ASSERT_EQ(serializer1.get_buffer(), serializer2.get_buffer());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -235,7 +235,7 @@ public:
|
|||||||
|
|
||||||
std::wstring name{};
|
std::wstring name{};
|
||||||
|
|
||||||
std::optional<uint32_t> exit_status{};
|
std::optional<NTSTATUS> exit_status{};
|
||||||
std::optional<handle> await_object{};
|
std::optional<handle> await_object{};
|
||||||
bool waiting_for_alert{false};
|
bool waiting_for_alert{false};
|
||||||
bool alerted{false};
|
bool alerted{false};
|
||||||
@@ -353,6 +353,7 @@ struct process_context
|
|||||||
uint64_t previous_ip{0};
|
uint64_t previous_ip{0};
|
||||||
|
|
||||||
std::optional<uint64_t> exception_rip{};
|
std::optional<uint64_t> exception_rip{};
|
||||||
|
std::optional<NTSTATUS> exit_status{};
|
||||||
|
|
||||||
emulator_allocator base_allocator;
|
emulator_allocator base_allocator;
|
||||||
|
|
||||||
@@ -390,6 +391,7 @@ struct process_context
|
|||||||
buffer.write(this->current_ip);
|
buffer.write(this->current_ip);
|
||||||
buffer.write(this->previous_ip);
|
buffer.write(this->previous_ip);
|
||||||
buffer.write_optional(this->exception_rip);
|
buffer.write_optional(this->exception_rip);
|
||||||
|
buffer.write_optional(this->exit_status);
|
||||||
buffer.write(this->base_allocator);
|
buffer.write(this->base_allocator);
|
||||||
buffer.write(this->peb);
|
buffer.write(this->peb);
|
||||||
buffer.write(this->process_params);
|
buffer.write(this->process_params);
|
||||||
@@ -424,6 +426,7 @@ struct process_context
|
|||||||
buffer.read(this->current_ip);
|
buffer.read(this->current_ip);
|
||||||
buffer.read(this->previous_ip);
|
buffer.read(this->previous_ip);
|
||||||
buffer.read_optional(this->exception_rip);
|
buffer.read_optional(this->exception_rip);
|
||||||
|
buffer.read_optional(this->exit_status);
|
||||||
buffer.read(this->base_allocator);
|
buffer.read(this->base_allocator);
|
||||||
buffer.read(this->peb);
|
buffer.read(this->peb);
|
||||||
buffer.read(this->process_params);
|
buffer.read(this->process_params);
|
||||||
|
|||||||
@@ -1596,15 +1596,24 @@ namespace
|
|||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS handle_NtTerminateProcess(const syscall_context& c, const uint64_t process_handle,
|
NTSTATUS handle_NtTerminateProcess(const syscall_context& c, const uint64_t process_handle,
|
||||||
NTSTATUS /*exit_status*/)
|
NTSTATUS exit_status)
|
||||||
{
|
{
|
||||||
if (process_handle == 0)
|
if (process_handle == 0)
|
||||||
{
|
{
|
||||||
|
for (auto& t : c.proc.threads)
|
||||||
|
{
|
||||||
|
if (&t.second != c.proc.active_thread)
|
||||||
|
{
|
||||||
|
t.second.exit_status = exit_status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (process_handle == ~0ULL)
|
if (process_handle == ~0ULL)
|
||||||
{
|
{
|
||||||
|
c.proc.exit_status = exit_status;
|
||||||
c.emu.stop();
|
c.emu.stop();
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
@@ -2126,16 +2135,8 @@ namespace
|
|||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS handle_NtAlertThreadByThreadIdEx(const syscall_context& c, const uint64_t thread_id,
|
NTSTATUS handle_NtAlertThreadByThreadId(const syscall_context& c, const uint64_t thread_id)
|
||||||
const emulator_object<RTL_SRWLOCK> lock)
|
|
||||||
{
|
{
|
||||||
if (lock.value())
|
|
||||||
{
|
|
||||||
puts("NtAlertThreadByThreadIdEx with lock not supported yet!");
|
|
||||||
//c.emu.stop();
|
|
||||||
//return STATUS_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& t : c.proc.threads)
|
for (auto& t : c.proc.threads)
|
||||||
{
|
{
|
||||||
if (t.second.id == thread_id)
|
if (t.second.id == thread_id)
|
||||||
@@ -2148,6 +2149,19 @@ namespace
|
|||||||
return STATUS_INVALID_HANDLE;
|
return STATUS_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS handle_NtAlertThreadByThreadIdEx(const syscall_context& c, const uint64_t thread_id,
|
||||||
|
const emulator_object<RTL_SRWLOCK> lock)
|
||||||
|
{
|
||||||
|
if (lock.value())
|
||||||
|
{
|
||||||
|
puts("NtAlertThreadByThreadIdEx with lock not supported yet!");
|
||||||
|
//c.emu.stop();
|
||||||
|
//return STATUS_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return handle_NtAlertThreadByThreadId(c, thread_id);
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS handle_NtWaitForAlertByThreadId(const syscall_context& c, const uint64_t,
|
NTSTATUS handle_NtWaitForAlertByThreadId(const syscall_context& c, const uint64_t,
|
||||||
const emulator_object<LARGE_INTEGER> timeout)
|
const emulator_object<LARGE_INTEGER> timeout)
|
||||||
{
|
{
|
||||||
@@ -2247,6 +2261,7 @@ void syscall_dispatcher::add_handlers(std::unordered_map<std::string, syscall_ha
|
|||||||
add_handler(NtDelayExecution);
|
add_handler(NtDelayExecution);
|
||||||
add_handler(NtWaitForAlertByThreadId);
|
add_handler(NtWaitForAlertByThreadId);
|
||||||
add_handler(NtAlertThreadByThreadIdEx);
|
add_handler(NtAlertThreadByThreadIdEx);
|
||||||
|
add_handler(NtAlertThreadByThreadId);
|
||||||
add_handler(NtReadFile);
|
add_handler(NtReadFile);
|
||||||
add_handler(NtSetInformationFile);
|
add_handler(NtSetInformationFile);
|
||||||
add_handler(NtUserRegisterWindowMessage);
|
add_handler(NtUserRegisterWindowMessage);
|
||||||
|
|||||||
@@ -425,7 +425,7 @@ namespace
|
|||||||
|
|
||||||
bool switch_to_thread(const logger& logger, x64_emulator& emu, process_context& context, emulator_thread& thread)
|
bool switch_to_thread(const logger& logger, x64_emulator& emu, process_context& context, emulator_thread& thread)
|
||||||
{
|
{
|
||||||
if (thread.exit_status.has_value() || !thread.is_thread_ready(context))
|
if (!thread.is_thread_ready(context))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -584,6 +584,11 @@ void emulator_thread::mark_as_ready(const NTSTATUS status)
|
|||||||
|
|
||||||
bool emulator_thread::is_thread_ready(process_context& context)
|
bool emulator_thread::is_thread_ready(process_context& context)
|
||||||
{
|
{
|
||||||
|
if(this->exit_status.has_value())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (this->waiting_for_alert)
|
if (this->waiting_for_alert)
|
||||||
{
|
{
|
||||||
if (this->alerted)
|
if (this->alerted)
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include "std_include.hpp"
|
||||||
|
|
||||||
#include <x64_emulator.hpp>
|
#include <x64_emulator.hpp>
|
||||||
|
|
||||||
#include "syscall_dispatcher.hpp"
|
#include "syscall_dispatcher.hpp"
|
||||||
|
|||||||
Reference in New Issue
Block a user