Skip to content

Commit a3dae96

Browse files
committed
fix
1 parent bae6b8c commit a3dae96

1 file changed

Lines changed: 56 additions & 8 deletions

File tree

source/yail.cpp

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <Windows.h>
55
#include <TlHelp32.h>
66
#include <winternl.h>
7+
#include <algorithm>
78
#include <array>
89
#include <format>
910
#include <fstream>
@@ -24,6 +25,41 @@ namespace
2425
}
2526
return p;
2627
}
28+
[[nodiscard]]
29+
std::size_t shellcode_section_size(const std::uint8_t* shell_code_start)
30+
{
31+
MEMORY_BASIC_INFORMATION memory_info{};
32+
if (!VirtualQuery(shell_code_start, &memory_info, sizeof(memory_info)))
33+
return 0;
34+
35+
const auto* image_base = static_cast<const std::uint8_t*>(memory_info.AllocationBase);
36+
const auto* dos_headers = reinterpret_cast<const IMAGE_DOS_HEADER*>(image_base);
37+
if (dos_headers->e_magic != IMAGE_DOS_SIGNATURE)
38+
return 0;
39+
40+
const auto* nt_headers = reinterpret_cast<const IMAGE_NT_HEADERS*>(image_base + dos_headers->e_lfanew);
41+
if (nt_headers->Signature != IMAGE_NT_SIGNATURE)
42+
return 0;
43+
44+
constexpr std::array<std::uint8_t, IMAGE_SIZEOF_SHORT_NAME> expected_name{'.', 'y', 'a', 'i', 'l'};
45+
const auto shell_code_rva =
46+
reinterpret_cast<std::uintptr_t>(shell_code_start) - reinterpret_cast<std::uintptr_t>(image_base);
47+
const auto* section = IMAGE_FIRST_SECTION(nt_headers);
48+
for (std::uint16_t i = 0; i < nt_headers->FileHeader.NumberOfSections; i++, section++)
49+
{
50+
if (!std::equal(expected_name.begin(), expected_name.end(), section->Name))
51+
continue;
52+
53+
const auto section_start = static_cast<std::size_t>(section->VirtualAddress);
54+
const auto section_size = static_cast<std::size_t>(section->Misc.VirtualSize);
55+
if (shell_code_rva < section_start || shell_code_rva - section_start >= section_size)
56+
return 0;
57+
58+
return section_size - (shell_code_rva - section_start);
59+
}
60+
61+
return 0;
62+
}
2763
struct LdrDataTableEntryFull final
2864
{
2965
LIST_ENTRY in_load_order_links;
@@ -117,8 +153,8 @@ namespace
117153
#pragma optimize("ts", on)
118154
#pragma strict_gs_check(push, off)
119155
#endif
120-
// Ordered COFF subsections keep the end marker adjacent after linking.
121-
__declspec(safebuffers) __declspec(noinline) __declspec(code_seg(".text$yail_shellcode$a")) DWORD WINAPI
156+
// A dedicated PE section keeps sizing independent from consumer linker ordering.
157+
__declspec(safebuffers) __declspec(noinline) __declspec(code_seg(".yail$a")) DWORD WINAPI
122158
remote_shellcode(const RemoteLoaderData* data)
123159
{
124160
auto* base = data->image_base;
@@ -340,8 +376,9 @@ namespace
340376

341377
return 0;
342378
}
343-
__declspec(noinline) __declspec(code_seg(".text$yail_shellcode$z")) void remote_shellcode_end()
379+
__declspec(noinline) __declspec(code_seg(".yail$z")) std::uint64_t remote_shellcode_end()
344380
{
381+
return 0x5941494C5348454Cull;
345382
}
346383

347384
#ifdef _MSC_VER
@@ -497,16 +534,27 @@ namespace yail
497534

498535
// Prepare shellcode page: [RemoteLoaderData | padding | shellcode bytes]
499536
const auto* shell_code_start = resolve_ilt(reinterpret_cast<void*>(&remote_shellcode));
537+
const auto* shell_code_end = resolve_ilt(reinterpret_cast<void*>(&remote_shellcode_end));
500538
const auto shell_code_start_address = reinterpret_cast<std::uintptr_t>(shell_code_start);
501-
const auto shell_code_end_address =
502-
reinterpret_cast<std::uintptr_t>(resolve_ilt(reinterpret_cast<void*>(&remote_shellcode_end)));
503-
if (shell_code_end_address <= shell_code_start_address)
539+
const auto shell_code_end_address = reinterpret_cast<std::uintptr_t>(shell_code_end);
540+
const auto section_size = shellcode_section_size(shell_code_start);
541+
542+
std::size_t size_of_shell_code = 0;
543+
if (shell_code_end_address > shell_code_start_address)
544+
{
545+
const auto marker_size = shell_code_end_address - shell_code_start_address;
546+
if (!section_size || marker_size <= section_size)
547+
size_of_shell_code = marker_size;
548+
}
549+
if (!size_of_shell_code)
550+
size_of_shell_code = section_size;
551+
552+
if (!size_of_shell_code)
504553
{
505554
VirtualFreeEx(process_handle, remote_image, 0, MEM_RELEASE);
506555
CloseHandle(process_handle);
507-
return std::unexpected("Invalid shellcode section layout");
556+
return std::unexpected("Failed to determine shellcode size");
508557
}
509-
const auto size_of_shell_code = shell_code_end_address - shell_code_start_address;
510558

511559
constexpr std::size_t data_aligned = (sizeof(RemoteLoaderData) + 0xF) & ~0xF;
512560
const std::size_t total_shellcode = data_aligned + size_of_shell_code;

0 commit comments

Comments
 (0)