Skip to content

Commit

Permalink
Basic working file writing
Browse files Browse the repository at this point in the history
  • Loading branch information
momo5502 committed Oct 22, 2024
1 parent 4b2adb0 commit af529a6
Show file tree
Hide file tree
Showing 5 changed files with 194 additions and 70 deletions.
2 changes: 1 addition & 1 deletion src/analyzer/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ namespace

(void)&watch_system_objects;
//watch_system_objects(win_emu);
win_emu.buffer_stdout = false;
win_emu.buffer_stdout = true;
//win_emu.verbose_calls = true;

const auto& exe = *win_emu.process().executable;
Expand Down
74 changes: 74 additions & 0 deletions src/common/utils/file_handle.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#pragma once

#include <cstdio>
#include <type_traits>

namespace utils
{
class file_handle
{
public:
file_handle() = default;

file_handle(FILE* file)
: file_(file)
{
}

~file_handle()
{
this->release();
}

file_handle(const file_handle&) = delete;
file_handle& operator=(const file_handle&) = delete;

file_handle(file_handle&& obj) noexcept
: file_handle()
{
this->operator=(std::move(obj));
}

file_handle& operator=(file_handle&& obj) noexcept
{
if (this != &obj)
{
this->release();
this->file_ = obj.file_;
obj.file_ = {};
}

return *this;
}

file_handle& operator=(FILE* file) noexcept
{
this->release();
this->file_ = file;

return *this;
}

[[nodiscard]] operator bool() const
{
return this->file_;
}

[[nodiscard]] operator FILE*() const
{
return this->file_;
}

private:
FILE* file_{};

void release()
{
if (this->file_)
{
(void)fclose(this->file_);
this->file_ = {};
}
}
};
}
6 changes: 4 additions & 2 deletions src/windows-emulator/process_context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@

#include "module/module_manager.hpp"
#include <utils/nt_handle.hpp>
#include <utils/file_handle.hpp>

#include <x64_emulator.hpp>


#define PEB_SEGMENT_SIZE (1 << 20) // 1 MB
#define GS_SEGMENT_SIZE (1 << 20) // 1 MB

Expand Down Expand Up @@ -80,7 +82,7 @@ struct event : ref_counted_object

struct file
{
utils::nt::handle<utils::nt::invalid_handle> handle{};
utils::file_handle handle{};
std::wstring name{};

void serialize(utils::buffer_serializer& buffer) const
Expand All @@ -92,7 +94,7 @@ struct file
void deserialize(utils::buffer_deserializer& buffer)
{
buffer.read(this->name);
this->handle = INVALID_HANDLE_VALUE;
this->handle = {};
}
};

Expand Down
9 changes: 9 additions & 0 deletions src/windows-emulator/syscall_utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,15 @@ T resolve_argument(x64_emulator& emu, const size_t index)
return static_cast<T>(arg);
}

template <typename T>
requires(std::is_same_v<std::remove_cvref_t<T>, handle>)
handle resolve_argument(x64_emulator& emu, const size_t index)
{
handle h{};
h.bits = resolve_argument<uint64_t>(emu, index);
return h;
}

template <typename T>
requires(std::is_same_v<T, emulator_object<typename T::value_type>>)
T resolve_argument(x64_emulator& emu, const size_t index)
Expand Down
173 changes: 106 additions & 67 deletions src/windows-emulator/syscalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,44 +221,6 @@ namespace
return STATUS_SUCCESS;
}

NTSTATUS handle_NtOpenFile(const syscall_context& c,
const emulator_object<uint64_t> file_handle,
const ACCESS_MASK desired_access,
const emulator_object<OBJECT_ATTRIBUTES> object_attributes,
const emulator_object<IO_STATUS_BLOCK> /*io_status_block*/,
const ULONG share_access,
const ULONG open_options)
{
file f{};
const auto attributes = object_attributes.read();
f.name = read_unicode_string(c.emu, attributes.ObjectName);

UNICODE_STRING string{};
string.Buffer = f.name.data();
string.Length = static_cast<uint16_t>(f.name.size() * 2);
string.MaximumLength = string.Length;

OBJECT_ATTRIBUTES new_attributes{};
new_attributes.ObjectName = &string;
new_attributes.Length = sizeof(new_attributes);

HANDLE h{};
IO_STATUS_BLOCK status_block{};

const auto res = NtOpenFile(&h, desired_access, &new_attributes, &status_block, share_access, open_options);
if (res != STATUS_SUCCESS)
{
return res;
}

f.handle = h;

const auto handle = c.proc.files.store(std::move(f));
file_handle.write(handle.bits);

return STATUS_SUCCESS;
}

NTSTATUS handle_NtOpenSection(const syscall_context& c, const emulator_object<uint64_t> section_handle,
const ACCESS_MASK /*desired_access*/,
const emulator_object<OBJECT_ATTRIBUTES> object_attributes)
Expand Down Expand Up @@ -1531,28 +1493,81 @@ namespace
return STATUS_NOT_SUPPORTED;
}

NTSTATUS handle_NtWriteFile(const syscall_context& c, const uint64_t file_handle, const uint64_t /*event*/,
NTSTATUS handle_NtWriteFile(const syscall_context& c, const handle file_handle, const uint64_t /*event*/,
const uint64_t /*apc_routine*/,
const uint64_t /*apc_context*/,
const emulator_object<IO_STATUS_BLOCK> /*io_status_block*/,
uint64_t buffer, const ULONG length,
const emulator_object<LARGE_INTEGER> /*byte_offset*/,
const emulator_object<ULONG> /*key*/)
{
std::string temp_buffer{};
temp_buffer.resize(length);
c.emu.read_memory(buffer, temp_buffer.data(), temp_buffer.size());


if (file_handle == STDOUT_HANDLE)
{
std::string temp_buffer{};
temp_buffer.resize(length);
c.emu.read_memory(buffer, temp_buffer.data(), temp_buffer.size());

c.win_emu.logger.info("%.*s", static_cast<int>(temp_buffer.size()), temp_buffer.data());

return STATUS_SUCCESS;
}

//puts("NtWriteFile not supported");
c.emu.stop();
return STATUS_NOT_SUPPORTED;
const auto* f = c.proc.files.get(file_handle);
if (!f)
{
return STATUS_INVALID_HANDLE;
}

(void)fwrite(temp_buffer.data(), 1, temp_buffer.size(), f->handle);
return STATUS_SUCCESS;
}

const wchar_t* map_mode(const ACCESS_MASK desired_access, const ULONG create_disposition)
{
const wchar_t* mode = L"";

switch (create_disposition)
{
case FILE_CREATE:
case FILE_SUPERSEDE:
if (desired_access & GENERIC_WRITE)
{
mode = L"w";
}
break;

case FILE_OPEN:
case FILE_OPEN_IF:
if (desired_access & GENERIC_WRITE)
{
mode = L"r+";
}
else if (desired_access & GENERIC_READ)
{
mode = L"r";
}
break;

case FILE_OVERWRITE:
case FILE_OVERWRITE_IF:
if (desired_access & GENERIC_WRITE)
{
mode = L"w+";
}
break;

default:
mode = L"";
break;
}

if (desired_access & FILE_APPEND_DATA)
{
mode = L"a";
}

return mode;
}

NTSTATUS handle_NtCreateFile(const syscall_context& c, const emulator_object<uint64_t> file_handle,
Expand Down Expand Up @@ -1590,39 +1605,63 @@ namespace
file f{};
f.name = std::move(filename);

UNICODE_STRING string{};
string.Buffer = f.name.data();
string.Length = static_cast<uint16_t>(f.name.size() * 2);
string.MaximumLength = string.Length;

OBJECT_ATTRIBUTES new_attributes{};
new_attributes.ObjectName = &string;
new_attributes.Length = sizeof(new_attributes);
if (attributes.RootDirectory)
{
const auto* root = c.proc.files.get(reinterpret_cast<uint64_t>(attributes.RootDirectory));
if (!root)
{
return STATUS_INVALID_HANDLE;
}

HANDLE h{};
f.name = root->name + f.name;
}

NTSTATUS res{STATUS_SUCCESS};
io_status_block.access([&](IO_STATUS_BLOCK& block)
if (f.name.ends_with(L"\\"))
{
res = NtCreateFile(&h, desired_access, &new_attributes, &block, nullptr, file_attributes, share_access,
create_disposition, create_options, nullptr, 0);
});
const auto handle = c.proc.files.store(std::move(f));
file_handle.write(handle.bits);

return STATUS_SUCCESS;
}

const auto* mode = map_mode(desired_access, create_disposition);

if (res != STATUS_SUCCESS)
FILE* file{};
const auto error = _wfopen_s(&file, f.name.c_str(), mode);

if (!file)
{
return res;
switch (error)
{
case ENOENT:
return STATUS_OBJECT_NAME_NOT_FOUND;
case EACCES:
return STATUS_ACCESS_DENIED;
case EISDIR:
return STATUS_FILE_IS_A_DIRECTORY;
default:
return STATUS_NOT_SUPPORTED;
}
}

f.handle = h;
f.handle = file;

const auto handle = c.proc.files.store(std::move(f));
file_handle.write(handle.bits);

return res;

return STATUS_SUCCESS;
}

//printf("Unsupported file: %S\n", filename.c_str());
//return STATUS_NOT_SUPPORTED;
NTSTATUS handle_NtOpenFile(const syscall_context& c,
const emulator_object<uint64_t> file_handle,
const ACCESS_MASK desired_access,
const emulator_object<OBJECT_ATTRIBUTES> object_attributes,
const emulator_object<IO_STATUS_BLOCK> io_status_block,
const ULONG share_access,
const ULONG open_options)
{
return handle_NtCreateFile(c, file_handle, desired_access, object_attributes, io_status_block, {}, 0,
share_access, FILE_OPEN, open_options, 0, 0);
}

NTSTATUS handle_NtQueryInformationJobObject()
Expand Down

0 comments on commit af529a6

Please sign in to comment.