Skip to content

Commit

Permalink
Initial support for win64
Browse files Browse the repository at this point in the history
  • Loading branch information
moonshadow565 committed Mar 25, 2023
1 parent 1c9f82a commit a5dd658
Show file tree
Hide file tree
Showing 8 changed files with 157 additions and 111 deletions.
Empty file modified cslol-tools/lib/lol/patcher/asm/build.sh
100644 → 100755
Empty file.
12 changes: 6 additions & 6 deletions cslol-tools/lib/lol/patcher/asm/defines.asm
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
; define offsets for payload data structure
[bits 32]
[bits 64]

%define payload_org_open_ptr 0
%define payload_prefix_open_ptr 4
%define payload_wopen 8
%define payload_org_alloc_ptr 12
%define payload_find_ret_addr 16
%define payload_hook_ret_addr 20
%define payload_prefix_open_ptr 8
%define payload_wopen 16
%define payload_org_alloc_ptr 24
%define payload_find_ret_addr 32
%define payload_hook_ret_addr 40
94 changes: 55 additions & 39 deletions cslol-tools/lib/lol/patcher/asm/file_hook.asm
Original file line number Diff line number Diff line change
@@ -1,44 +1,51 @@
%include 'defines.asm'

; args
%define arg_lpFileName 8
%define arg_dwDesiredAccess 12
%define arg_dwShareMode 16
%define arg_lpSecurityAttributes 20
%define arg_dwCreationDisposition 24
%define arg_dwFlagsAndAttributes 28
%define arg_hTemplateFile 32
%define arg_lpFileName 16
%define arg_dwDesiredAccess 24
%define arg_dwShareMode 32
%define arg_lpSecurityAttributes 40
%define arg_dwCreationDisposition 48
%define arg_dwFlagsAndAttributes 56
%define arg_hTemplateFile 72

; locals
%define local_buffer_size 0x1000
%define local_buffer -local_buffer_size

; prologue
enter local_buffer_size, 0
push ebx
push edi
push esi
push rbx
push rdi
push rsi
sub rsp, 72

; use original functions shadow stack to preserve original args
mov arg_lpSecurityAttributes[rbp], r9
mov arg_dwShareMode[rbp], r8
mov arg_dwDesiredAccess[rbp], rdx
mov arg_lpFileName[rbp], rcx

; get pointer to data after function
call back
back: pop ebx
and ebx, 0xFFFFF000
back: pop rbx
and rbx, 0xFFFFFFFFFFFFF000

; prepare buffer for writing
lea edi, DWORD local_buffer[ebp]
lea rdi, QWORD local_buffer[rbp]

; write prefix
mov esi, DWORD payload_prefix_open_ptr[ebx]
mov rsi, QWORD payload_prefix_open_ptr[rbx]
write_prefix: lodsw
stosw
test ax, ax
jne write_prefix

; remove null terminator
sub edi, 2
sub rdi, 2

; write path
mov esi, DWORD arg_lpFileName[ebp]
mov rsi, arg_lpFileName[rbp]
mov ah, 0
write_path: lodsb
cmp al, 47
Expand All @@ -49,34 +56,43 @@ write_path_skip:
test al, al
jne write_path

; call original with modified buffer
lea eax, DWORD local_buffer[ebp]
push DWORD arg_hTemplateFile[ebp]
push DWORD arg_dwFlagsAndAttributes[ebp]
push DWORD arg_dwCreationDisposition[ebp]
push DWORD arg_lpSecurityAttributes[ebp]
push DWORD arg_dwShareMode[ebp]
push DWORD arg_dwDesiredAccess[ebp]
push eax
call DWORD payload_wopen[ebx]

; call wide with modified buffer
mov rax, arg_hTemplateFile[rbp]
mov [rsp+48], rax
mov rax, arg_dwFlagsAndAttributes[rbp]
mov [rsp+40], rax
mov rax, arg_dwCreationDisposition[rbp]
mov [rsp+32], rax
mov r9, arg_lpSecurityAttributes[rbp]
mov r8, arg_dwShareMode[rbp]
mov rdx, arg_dwDesiredAccess[rbp]
lea rcx, QWORD local_buffer[rbp]
call QWORD payload_wopen[rbx]

; restore original arguments
; check for success
cmp eax, -1
cmp rax, -1
jne done

; just call original
push DWORD arg_hTemplateFile[ebp]
push DWORD arg_dwFlagsAndAttributes[ebp]
push DWORD arg_dwCreationDisposition[ebp]
push DWORD arg_lpSecurityAttributes[ebp]
push DWORD arg_dwShareMode[ebp]
push DWORD arg_dwDesiredAccess[ebp]
push DWORD arg_lpFileName[ebp]
call DWORD payload_org_open_ptr[ebx]
mov rax, arg_hTemplateFile[rbp]
mov [rsp+48], rax
mov rax, arg_dwFlagsAndAttributes[rbp]
mov [rsp+40], rax
mov rax, arg_dwCreationDisposition[rbp]
mov [rsp+32], rax
mov r9, arg_lpSecurityAttributes[rbp]
mov r8, arg_dwShareMode[rbp]
mov rdx, arg_dwDesiredAccess[rbp]
mov rcx, arg_lpFileName[rbp]
call QWORD payload_org_open_ptr[rbx]


; epilogue
done: pop esi
pop edi
pop ebx
done: add rsp, 72
pop rsi
pop rdi
pop rbx
leave
ret 28
ret
14 changes: 7 additions & 7 deletions cslol-tools/lib/lol/patcher/asm/ret_hook.asm
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
%include 'defines.asm'

call back
back: pop eax
and eax, 0xFFFFF000
mov eax, DWORD payload_find_ret_addr[eax]
push eax
; following two lines are just shorter way to do: mov eax, 1
xor eax,eax
inc eax
back: pop rax
and rax, 0xFFFFFFFFFFFFF000
mov rax, QWORD payload_find_ret_addr[rax]
push rax
; following two lines are just shorter way to do: mov rax, 1
xor rax,rax
inc rax
ret
40 changes: 20 additions & 20 deletions cslol-tools/lib/lol/patcher/asm/up_hook.asm
Original file line number Diff line number Diff line change
@@ -1,38 +1,38 @@
%include 'defines.asm'

; config
%define config_scan_size 0x40
%define config_scan_size 0x80

; args
%define arg_str 8
%define arg_file 12
%define arg_line 16
%define arg_str rcx
%define arg_file rdx
%define arg_line r8

; prologue
enter 0, 0
push ebx
push esi
push rbx
push rsi
call back
back: pop ebx
and ebx, 0xFFFFF000
back: pop rbx
and rbx, 0xFFFFFFFFFFFFF000

; scanning the stack
mov esi, DWORD payload_find_ret_addr[ebx]
mov eax, ebp
add eax, config_scan_size
scan: sub eax, 4
cmp eax, ebp
mov rsi, QWORD payload_find_ret_addr[rbx]
mov rax, rbp
add rax, config_scan_size
scan: sub rax, 8
cmp rax, rbp
je done
cmp esi, DWORD [eax]
cmp rsi, QWORD [rax]
jne scan
mov esi, DWORD payload_hook_ret_addr[ebx]
mov DWORD [eax], esi
mov rsi, QWORD payload_hook_ret_addr[rbx]
mov QWORD [rax], rsi

; fetch resume address
done: mov eax, DWORD payload_org_alloc_ptr[ebx]
done: mov rax, QWORD payload_org_alloc_ptr[rbx]

; epilogue
pop esi
pop ebx
pop rsi
pop rbx
leave
jmp eax
jmp rax
102 changes: 68 additions & 34 deletions cslol-tools/lib/lol/patcher/patcher_win32.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,30 +16,37 @@ using namespace lol;
using namespace lol::patcher;
using namespace std::chrono_literals;

constexpr auto const find_open = &ppp::any<"6A 00 56 55 50 FF 15 o[u[?? ?? ?? ??]] 8B F8"_pattern>;
constexpr auto const find_ret = &ppp::any<"68 A0 02 00 00 E8 .... o[83] C4 50"_pattern>;
constexpr auto const find_wopen = &ppp::any<"6A 00 6A ?? 68 ?? ?? 12 00 ?? FF 15 u[?? ?? ?? ??]"_pattern>;
// clang-format off
constexpr auto const find_open =
&ppp::any<"44 8B C3 "
"41 8B D6 "
"89 7C 24 ?? "
"49 8B CC "
"FF 15 o[r[?? ?? ?? ??]]"_pattern>;
constexpr auto const find_ret =
&ppp::any<"B9 A0 02 00 00 "
"48 89 ?? ?? ?? "
"E8 ?? ?? ?? ?? "
"o[??]"_pattern>;
constexpr auto const find_wopen =
&ppp::any<"BA 9F 01 12 00 "
"C7 44 24 ?? 02 00 00 00 "
"45 8D ?? ?? "
"FF 15 r[?? ?? ?? ??]"_pattern>;
constexpr auto const find_alloc =
&ppp::any<"A1 u[?? ?? ?? ??] "
"85 C0 "
"74 09 "
"3D ?? ?? ?? ?? "
"74 02 "
"FF E0 "
"8B 44 24 04 "
"85 C0 "
"75 01 "
&ppp::any<"48 83 C4 28 "
"C3 "
"50 "
"C7 05 ?? ?? ?? ?? 00 00 00 00 "
"E8 r[?? ?? ?? ??]"_pattern>;
"C7 05 r[?? ?? ?? ??] 00 00 00 00 "
"48 83 C4 28 "
"E9 r[?? ?? ?? ??]"_pattern>;
// clang-format on

struct ImportTrampoline {
uint8_t data[64] = {};

static ImportTrampoline make(Ptr<uint8_t> where) {
ImportTrampoline result = {{0xB8u, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE0}};
memcpy(result.data + 1, &where, sizeof(where));
ImportTrampoline result = {{0x48, 0xB8u, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE0}};
memcpy(result.data + 2, &where, sizeof(where));
return result;
}
};
Expand All @@ -53,32 +60,58 @@ struct CodePayload {
Ptr<uint8_t> find_ret_addr = {};
Ptr<uint8_t> hook_ret_addr = {};

// clang-format off
// Actual data and shellcode storage
uint8_t hook_open_data[0x80] = {
0xc8, 0x00, 0x10, 0x00, 0x53, 0x57, 0x56, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x81, 0xe3, 0x00, 0xf0, 0xff,
0xff, 0x8d, 0xbd, 0x00, 0xf0, 0xff, 0xff, 0x8b, 0x73, 0x04, 0x66, 0xad, 0x66, 0xab, 0x66, 0x85, 0xc0, 0x75,
0xf7, 0x83, 0xef, 0x02, 0x8b, 0x75, 0x08, 0xb4, 0x00, 0xac, 0x3c, 0x2f, 0x75, 0x02, 0xb0, 0x5c, 0x66, 0xab,
0x84, 0xc0, 0x75, 0xf3, 0x8d, 0x85, 0x00, 0xf0, 0xff, 0xff, 0xff, 0x75, 0x20, 0xff, 0x75, 0x1c, 0xff, 0x75,
0x18, 0xff, 0x75, 0x14, 0xff, 0x75, 0x10, 0xff, 0x75, 0x0c, 0x50, 0xff, 0x53, 0x08, 0x83, 0xf8, 0xff, 0x75,
0x17, 0xff, 0x75, 0x20, 0xff, 0x75, 0x1c, 0xff, 0x75, 0x18, 0xff, 0x75, 0x14, 0xff, 0x75, 0x10, 0xff, 0x75,
0x0c, 0xff, 0x75, 0x08, 0xff, 0x13, 0x5e, 0x5f, 0x5b, 0xc9, 0xc2, 0x1c, 0x00,
uint8_t hook_open_data[0xC0] = {
0xc8, 0x00, 0x10, 0x00, 0x53, 0x57, 0x56, 0x48,
0x83, 0xec, 0x48, 0x4c, 0x89, 0x4d, 0x28, 0x4c,
0x89, 0x45, 0x20, 0x48, 0x89, 0x55, 0x18, 0x48,
0x89, 0x4d, 0x10, 0xe8, 0x00, 0x00, 0x00, 0x00,
0x5b, 0x48, 0x81, 0xe3, 0x00, 0xf0, 0xff, 0xff,
0x48, 0x8d, 0xbd, 0x00, 0xf0, 0xff, 0xff, 0x48,
0x8b, 0x73, 0x08, 0x66, 0xad, 0x66, 0xab, 0x66,
0x85, 0xc0, 0x75, 0xf7, 0x48, 0x83, 0xef, 0x02,
0x48, 0x8b, 0x75, 0x10, 0xb4, 0x00, 0xac, 0x3c,
0x2f, 0x75, 0x02, 0xb0, 0x5c, 0x66, 0xab, 0x84,
0xc0, 0x75, 0xf3, 0x48, 0x8b, 0x45, 0x48, 0x48,
0x89, 0x44, 0x24, 0x30, 0x48, 0x8b, 0x45, 0x38,
0x48, 0x89, 0x44, 0x24, 0x28, 0x48, 0x8b, 0x45,
0x30, 0x48, 0x89, 0x44, 0x24, 0x20, 0x4c, 0x8b,
0x4d, 0x28, 0x4c, 0x8b, 0x45, 0x20, 0x48, 0x8b,
0x55, 0x18, 0x48, 0x8d, 0x8d, 0x00, 0xf0, 0xff,
0xff, 0xff, 0x53, 0x10, 0x48, 0x83, 0xf8, 0xff,
0x75, 0x2d, 0x48, 0x8b, 0x45, 0x48, 0x48, 0x89,
0x44, 0x24, 0x30, 0x48, 0x8b, 0x45, 0x38, 0x48,
0x89, 0x44, 0x24, 0x28, 0x48, 0x8b, 0x45, 0x30,
0x48, 0x89, 0x44, 0x24, 0x20, 0x4c, 0x8b, 0x4d,
0x28, 0x4c, 0x8b, 0x45, 0x20, 0x48, 0x8b, 0x55,
0x18, 0x48, 0x8b, 0x4d, 0x10, 0xff, 0x13, 0x48,
0x83, 0xc4, 0x48, 0x5e, 0x5f, 0x5b, 0xc9, 0xc3
};
uint8_t hook_alloc_data[0x40] = {
0xc8, 0x00, 0x00, 0x00, 0x53, 0x56, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x81, 0xe3, 0x00, 0xf0, 0xff, 0xff,
0x8b, 0x73, 0x10, 0x89, 0xe8, 0x83, 0xc0, 0x40, 0x83, 0xe8, 0x04, 0x39, 0xe8, 0x74, 0x09, 0x3b, 0x30, 0x75,
0xf5, 0x8b, 0x73, 0x14, 0x89, 0x30, 0x8b, 0x43, 0x0c, 0x5e, 0x5b, 0xc9, 0xff, 0xe0,
0xc8, 0x00, 0x00, 0x00, 0x53, 0x56, 0xe8, 0x00,
0x00, 0x00, 0x00, 0x5b, 0x48, 0x81, 0xe3, 0x00,
0xf0, 0xff, 0xff, 0x48, 0x8b, 0x73, 0x20, 0x48,
0x89, 0xe8, 0x48, 0x05, 0x80, 0x00, 0x00, 0x00,
0x48, 0x83, 0xe8, 0x08, 0x48, 0x39, 0xe8, 0x74,
0x0c, 0x48, 0x3b, 0x30, 0x75, 0xf2, 0x48, 0x8b,
0x73, 0x28, 0x48, 0x89, 0x30, 0x48, 0x8b, 0x43,
0x18, 0x5e, 0x5b, 0xc9, 0xff, 0xe0
};
uint8_t hook_ret_data[0x40] = {
0xe8, 0x00, 0x00, 0x00, 0x00, 0x58, 0x25, 0x00, 0xf0, 0xff, 0xff, 0x8b, 0x40, 0x10, 0x50, 0x31, 0xc0, 0x40,
0xc3,
0xe8, 0x00, 0x00, 0x00, 0x00, 0x58, 0x48, 0x25,
0x00, 0xf0, 0xff, 0xff, 0x48, 0x8b, 0x40, 0x20,
0x50, 0x48, 0x31, 0xc0, 0x48, 0xff, 0xc0, 0xc3
};
// clang-format on

ImportTrampoline org_open_data = {};
char16_t prefix_open_data[0x400] = {};
};

struct Context {
LineConfig<std::uint32_t,
"patcher-win32-v11",
LineConfig<std::uint64_t,
"patcher-win64-v1",
"checksum",
"open",
"open_ref",
Expand Down Expand Up @@ -148,7 +181,7 @@ struct Context {
config.get<"open">() = process.Debase((PtrStorage)std::get<2>(*open_match));
config.get<"wopen">() = process.Debase((PtrStorage)std::get<1>(*wopen_match));
config.get<"ret">() = process.Debase((PtrStorage)std::get<1>(*ret_match));
config.get<"alloc_ptr">() = process.Debase((PtrStorage)std::get<1>(*alloc_match));
config.get<"alloc_ptr">() = process.Debase((PtrStorage)std::get<1>(*alloc_match) + 8);
config.get<"alloc_fn">() = process.Debase((PtrStorage)std::get<2>(*alloc_match));
config.get<"checksum">() = process.Checksum();
}
Expand All @@ -159,7 +192,8 @@ struct Context {

auto is_patchable(const Process& process) const noexcept -> bool {
auto const open_ref = process.Rebase<PtrStorage>(config.get<"open_ref">());
if (auto result = process.TryRead(open_ref); !result || *result != process.Rebase(config.get<"open">())) {
auto const open_diff = (std::uint32_t)(config.get<"open">() - (config.get<"open_ref">() + 4));
if (auto result = process.TryRead(open_ref); !result || (std::uint32_t)*result != open_diff) {
return false;
}

Expand Down
4 changes: 0 additions & 4 deletions cslol-tools/lib/lol/patcher/utility/process.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,7 @@ namespace lol::patcher {
template <typename T>
Ptr(T *) -> Ptr<T>;

#ifdef WIN32
using PtrStorage = uint32_t;
#else
using PtrStorage = uint64_t;
#endif

template <>
struct Ptr<void> {
Expand Down
2 changes: 1 addition & 1 deletion cslol-tools/lib/lol/patcher/utility/process_win32.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ auto Process::Checksum() const -> uint32_t {
if (dos->e_magic != IMAGE_DOS_SIGNATURE) {
lol_throw_msg("Failed to get dos header signature!");
}
auto const nt = (PIMAGE_NT_HEADERS32)(raw + dos->e_lfanew);
auto const nt = (PIMAGE_NT_HEADERS64)(raw + dos->e_lfanew);
if (nt->Signature != IMAGE_NT_SIGNATURE) {
lol_throw_msg("Failed to get nt header signature!");
}
Expand Down

0 comments on commit a5dd658

Please sign in to comment.