Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add x86_64 support #97

Open
wants to merge 21 commits into
base: x86_64
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
8bf7233
Added "debug" target in Makefile
cube0x8 Feb 15, 2021
9a2ee40
Added ARCH target flag for the peloader library. Added first test whi…
cube0x8 Feb 17, 2021
15ad102
Modified test target.
cube0x8 Feb 26, 2021
de07f73
a x64 PE is mapped and linked.
cube0x8 Feb 26, 2021
77497a9
Created skeleton for x64 APIs loading.
cube0x8 Mar 3, 2021
4d8d7b0
Removed libdisasm and imported zydis as submodule. libdisasm has been…
cube0x8 Mar 22, 2021
bc565fe
Added x86_64 support for libhook and added assembly dispatchers to re…
cube0x8 Apr 9, 2021
cb17618
x86_64 WINAPIs are correctly dispatched and mpclient boots up and sca…
cube0x8 May 9, 2021
56f4b3e
Added x86_64_call_exported_function wrapper to call DLL exports.
cube0x8 May 11, 2021
844c5fe
Fixed bug on stack alignment for x64 dispatchers and added priority f…
cube0x8 May 12, 2021
97d3bec
No redzone for mpclient_x64 and peloader. The subhook hooks were push…
cube0x8 May 14, 2021
188676c
The jmp from the fixup area to the x86_64 dispatcher is made by subho…
cube0x8 May 23, 2021
8ecacf9
Added check on setup_call_to_dispatcher return value. Integrated log.…
cube0x8 May 29, 2021
020b7a7
It looks like __attribute__((ms_abi)) can spawn deamons, resurrect th…
cube0x8 May 29, 2021
3a0edb7
x64 NASM dispatchers are not useful anymore :( re-written the libhook…
cube0x8 May 29, 2021
5c65a4f
Implemented remove_function_redirect function
cube0x8 May 30, 2021
c827d74
Added -maccumulate-outgoing-args to compile mpclient_x64, since it al…
cube0x8 May 30, 2021
9675382
Added x64 SEH support
cube0x8 Jul 16, 2021
04cda3f
Removed a __debugbreak() in the wrong place and freed FunctionEntry a…
cube0x8 Jul 19, 2021
d4acd2b
both mpclient and mpclient_x64 compile
cube0x8 Jul 27, 2021
5c344a0
Removed NASM dependency
cube0x8 Jul 28, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
*.vdm
*.exe
mpclient
mpclient_x64
avscript
eicar.com
.gradle/
.idea/
mpcache-*
6 changes: 6 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[submodule "intercept/zydis"]
path = intercept/zydis
url = https://github.com/zyantific/zydis.git
[submodule "intercept/subhook"]
path = intercept/subhook
url = https://github.com/cube0x8/subhook.git
51 changes: 40 additions & 11 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,28 +1,57 @@
CFLAGS = -O3 -march=native -ggdb3 -m32 -std=gnu99 -fshort-wchar -Wno-multichar -Iinclude -mstackrealign
CPPFLAGS=-DNDEBUG -D_GNU_SOURCE -I. -Iintercept -Ipeloader
LDFLAGS = $(CFLAGS) -m32 -lm -Wl,--dynamic-list=exports.lst
LDLIBS = intercept/libdisasm.a -Wl,--whole-archive,peloader/libpeloader.a,--no-whole-archive
CFLAGS = -march=native -ggdb3 -std=gnu99 -fshort-wchar -Wno-multichar -Iinclude -Iintercept/include -Ilog -Ipeloader -mstackrealign -maccumulate-outgoing-args
CPPFLAGS= -D_GNU_SOURCE -I.
LDFLAGS = $(CFLAGS) -lm -Wl,--dynamic-list=exports.lst -ldl
LDLIBS = -Wl,--whole-archive peloader/libpeloader.a -Wl,intercept/libhook.a -Wl,intercept/libZydis.a -Wl,intercept/libsubhook.a -Wl,--no-whole-archive

.PHONY: clean peloader intercept

TARGETS=mpclient | peloader
RELEASE_CFLAGS = -O3
RELEASE_CPPFLAGS = -DNDEBUG
DEBUG_CFLAGS = -O0 -g

TARGETS=mpclient mpclient_x64 | peloader

all: CFLAGS += $(RELEASE_CFLAGS)
all: CPPFLAGS += $(RELEASE_CPPFLAGS)
all: BUILD_TARGET = "all"
all: $(TARGETS)
-mkdir -p faketemp

debug: CFLAGS += $(DEBUG_CFLAGS)
debug: BUILD_TARGET = "debug"
debug: CMAKE_FLAGS = -DCMAKE_BUILD_TYPE=Debug
debug: $(TARGETS)
-mkdir -p faketemp

intercept:
make -C intercept all
cd intercept; mkdir build; cd build; cmake $(CMAKE_FLAGS) ..; make
cp intercept/build/libhook.a intercept/libhook.a
cp intercept/build/zydis/libZydis.a intercept/libZydis.a
cp intercept/build/subhook/libsubhook.a intercept/libsubhook.a

peloader:
make -C peloader all
make -C peloader ARCH=x86

peloader_x64:
make -C peloader debug ARCH=x64

intercept/hook.o: intercept
mpclient: CFLAGS += -m32
mpclient: LDFLAGS += -m32
mpclient: CMAKE_FLAGS += -DARCH:STRING=x86
mpclient: mpclient.o log/log.o | peloader intercept
$(CC) $(CFLAGS) $^ -o $@ $(LDLIBS) $(LDFLAGS)

mpclient_x64: CFLAGS += -g -O0 -fPIC
mpclient_x64: CMAKE_FLAGS = -DARCH:STRING=x64 -DCMAKE_BUILD_TYPE=Debug
mpclient_x64: mpclient_x64.o log/log.o | peloader_x64 intercept
$(CC) $(CFLAGS) $^ -o $@ $(LDLIBS) $(LDFLAGS)

mpclient: mpclient.o intercept/hook.o | peloader
test_seh: CFLAGS += -g -O0 -fPIC
test_seh: CMAKE_FLAGS = -DARCH:STRING=x64 -DCMAKE_BUILD_TYPE=Debug
test_seh: test_seh.o log/log.o | peloader_x64 intercept
$(CC) $(CFLAGS) $^ -o $@ $(LDLIBS) $(LDFLAGS)

clean:
rm -f a.out core *.o core.* vgcore.* gmon.out mpclient
make -C intercept clean
rm -rf a.out core *.o core.* vgcore.* gmon.out mpclient intercept/build intercept/*.a tests/build log/log.o
make -C peloader clean
rm -rf faketemp
16 changes: 8 additions & 8 deletions include/engineboot.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ typedef struct _ENGINE_INFO {
} ENGINE_INFO, *PENGINE_INFO;

typedef struct _ENGINE_CONFIG {
DWORD EngineFlags;
ulong EngineFlags;
PWCHAR Inclusions; // Example, "*.zip"
PVOID Exceptions;
PWCHAR UnknownString2;
Expand All @@ -52,9 +52,9 @@ typedef struct _ENGINE_CONFIG {
DWORD field_20;
DWORD field_24;
DWORD field_28;
DWORD field_2C; // Setting this seems to cause packer to be reported.
DWORD field_30;
DWORD field_34;
ulong field_2C; // Setting this seems to cause packer to be reported.
ulong field_30;
ulong field_34;
PCHAR UnknownAnsiString1;
PCHAR UnknownAnsiString2;
} ENGINE_CONFIG, *PENGINE_CONFIG;
Expand All @@ -64,7 +64,7 @@ typedef struct _ENGINE_CONTEXT {
} ENGINE_CONTEXT, *PENGINE_CONTEXT;

typedef struct _BOOTENGINE_PARAMS {
DWORD ClientVersion;
ulong ClientVersion;
PWCHAR SignatureLocation;
PVOID SpynetSource;
PENGINE_CONFIG EngineConfig;
Expand All @@ -74,16 +74,16 @@ typedef struct _BOOTENGINE_PARAMS {
PWCHAR LocalCopyDirectory;
PWCHAR OfflineTargetOS;
CHAR ProductString[16];
DWORD field_34;
ulong field_34;
PVOID GlobalCallback;
PENGINE_CONTEXT EngineContext;
DWORD AvgCpuLoadFactor;
ulong AvgCpuLoadFactor;
CHAR field_44[16];
PWCHAR SpynetReportingGUID;
PWCHAR SpynetVersion;
PWCHAR NISEngineVersion;
PWCHAR NISSignatureVersion;
DWORD FlightingEnabled;
ulong FlightingEnabled;
DWORD FlightingLevel;
PVOID DynamicConfig;
DWORD AutoSampleSubmission;
Expand Down
6 changes: 6 additions & 0 deletions include/mpclient.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#ifndef LOADLIBRARY_MPCLIENT_H
#define LOADLIBRARY_MPCLIENT_H

extern struct pe_image image;

#endif //LOADLIBRARY_MPCLIENT_H
19 changes: 9 additions & 10 deletions include/scanreply.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ typedef struct _SCANSTRUCT {
DWORD Flags;
PCHAR FileName;
CHAR VirusName[28];
DWORD field_28;
DWORD field_2C;
DWORD field_30;
DWORD field_34;
Expand All @@ -33,22 +32,22 @@ typedef struct _SCANSTRUCT {
DWORD field_44;
DWORD field_48;
DWORD field_4C;
DWORD FileSize;
DWORD field_54;
DWORD UserPtr;
DWORD field_5C;
ULONG64 FileSize;
ULONG64 UserPtr;
DWORD field_60;
DWORD field_64;
PCHAR MaybeFileName2;
PWCHAR StreamName1;
PWCHAR StreamName2;
DWORD field_6C;
DWORD ThreatId; // Can be passed back to GetThreatInfo
DWORD ThreatId; // Can be passed back to GetThreatInfo
} SCANSTRUCT, *PSCANSTRUCT;

typedef struct _SCAN_REPLY {
DWORD (*EngineScanCallback)(PSCANSTRUCT this);
DWORD field_4;
DWORD UserPtr;
DWORD field_C;
DWORD (*EngineScanCallback)(PSCANSTRUCT this);
DWORD field_4;
ULONG64 UserPtr;
DWORD field_C;
} SCAN_REPLY, *PSCAN_REPLY;

#pragma pack(pop)
Expand Down
24 changes: 12 additions & 12 deletions include/streambuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,21 +92,21 @@ enum {
};

typedef struct _STREAMBUFFER_DESCRIPTOR {
PVOID UserPtr;
DWORD (* Read)(PVOID this, uint64_t Offset, PVOID Buffer, DWORD Size, PDWORD SizeRead);
DWORD (* Write)(PVOID this, uint64_t Offset, PVOID Buffer, DWORD Size, PDWORD TotalWritten);
DWORD (* GetSize)(PVOID this, uint64_t *FileSize);
DWORD (* SetSize)(PVOID this, uint64_t *FileSize);
PWCHAR (* GetName)(PVOID this);
DWORD (* SetAttributes)(PVOID this, DWORD Attribute, PVOID Data, DWORD DataSize);
DWORD (* GetAttributes)(PVOID this, DWORD Attribute, PVOID Data, DWORD DataSize, PDWORD DataSizeWritten);
FILE *UserPtr;
DWORD (* Read)(FILE *fp, uint64_t Offset, PVOID Buffer, DWORD Size, PDWORD SizeRead);
DWORD (* Write)(FILE *fp, uint64_t Offset, PVOID Buffer, DWORD Size, PDWORD TotalWritten);
DWORD (* GetSize)(FILE *fp, uint64_t *FileSize);
DWORD (* SetSize)(FILE *fp, uint64_t *FileSize);
PWCHAR (* GetName)(FILE *fp);
DWORD (* SetAttributes)(FILE *fp, DWORD Attribute, PVOID Data, DWORD DataSize);
DWORD (* GetAttributes)(FILE *fp, DWORD Attribute, PVOID Data, DWORD DataSize, PDWORD DataSizeWritten);
} STREAMBUFFER_DESCRIPTOR, *PSTREAMBUFFER_DESCRIPTOR;

typedef struct _SCANSTREAM_PARAMS {
PSTREAMBUFFER_DESCRIPTOR Descriptor;
PSCAN_REPLY ScanReply;
DWORD UnknownB;
DWORD UnknownC;
PSTREAMBUFFER_DESCRIPTOR Descriptor;
PSCAN_REPLY ScanReply;
ULONG64 UnknownB;
ULONG64 UnknownC;
} SCANSTREAM_PARAMS, *PSCANSTREAM_PARAMS;

#pragma pack(pop)
Expand Down
4 changes: 4 additions & 0 deletions intercept/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
build*/
cmake-build*
Makefile
Testing
45 changes: 45 additions & 0 deletions intercept/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
cmake_minimum_required(VERSION "3.13")
project(hook C)

# set arch variables (default x86)
# to change the ARCH value to x64, pass -DARCH:STRING=x64 as argument to cmake command
set(ARCH "x86" CACHE STRING "user-specified architecture")
set(HOOK_SRC "./src/hook.c")

if(${ARCH} STREQUAL "x64")
set(HOOK_SRC "./src/hook_x86_64.c")
elseif(NOT ${ARCH} STREQUAL "x86")
message(FATAL_ERROR "Allowed ARCH values: x86, x64")
endif()

include_directories("./include")
include_directories("../log")

# Disable build of tools and examples.
option(ZYDIS_BUILD_TOOLS "" OFF)
option(ZYDIS_BUILD_EXAMPLES "" OFF)
# build subhook as static library and disable tests
option(SUBHOOK_STATIC "" ON)
option(SUBHOOK_TESTS "" OFF)
# force subhook to compile a 32bit library if ARCH == x86
if(${ARCH} STREQUAL "x86")
option(SUBHOOK_FORCE_32BIT "" ON)
endif()

# Register Zydis and subhook dependencies.
add_subdirectory("zydis")
add_subdirectory("subhook")

# Create our libhook static library
add_library("hook" ${HOOK_SRC})

# change build and linker options based on user-supplied ARCH value
if(${ARCH} STREQUAL "x86")
target_compile_options ( Zydis PUBLIC -m32 )
set_target_properties( hook PROPERTIES LINK_FLAGS -m32 )
endif()

# Have CMake link our project executable against Zydis and subhook.
target_link_libraries(hook PRIVATE "Zydis")
target_link_libraries(hook PRIVATE "subhook")
target_link_libraries(hook PRIVATE "x64_dispatcher")
11 changes: 0 additions & 11 deletions intercept/Makefile

This file was deleted.

63 changes: 49 additions & 14 deletions intercept/hook.h → intercept/include/hook.h
Original file line number Diff line number Diff line change
@@ -1,22 +1,31 @@
#ifndef __HOOK_H
#define __HOOK_H

bool insert_function_redirect(void *function, void *redirect, uint32_t flags);
bool remove_function_redirect(void *function);
bool redirect_call_within_function(void *function, void *target, void *redirect);
#include "../subhook/subhook.h"

// Flags recognised by insert_function_redirect.
enum {
HOOK_DEFAULT = 0,
HOOK_REPLACE_FUNCTION = (1 << 0), // Replace call, don't hook.
HOOK_FASTCALL = (1 << 1), // Try to minimize damage to registers.
enum ENUM_REDIRECT_FLAGS{
HOOK_DEFAULT = 0,
HOOK_REPLACE_FUNCTION = (1 << 0), // Replace call, don't hook.
HOOK_FASTCALL = (1 << 1), // Try to minimize damage to registers.
};

#ifdef __x86_64__
subhook_t insert_function_redirect(void *function, void *target, uint32_t flags);
bool remove_function_redirect(subhook_t hook);
bool redirect_call_within_function(void *function, void *target, void *redirect);
#else
bool insert_function_redirect(void *function, void *target, uint32_t flags);
bool remove_function_redirect(void *function);
bool redirect_call_within_function(void *function, void *target, void *redirect);
#endif

// Convenient representation of an x86 near call. The immediate operand is the
// relative, displaced branch target, thus actual address is something like:
//
// target = (uintptr_t)(&call) + sizeof(struct call) + call->operand.i;
//

struct __attribute__((packed)) branch {
uint8_t opcode;
union {
Expand All @@ -26,15 +35,41 @@ struct __attribute__((packed)) branch {
uint8_t data[0]; // Used to chain instructions together.
};

#define X86_OPCODE_CALL_NEAR 0xE8
#define X86_OPCODE_JMP_NEAR 0xE9
#ifdef __x86_64__
struct __attribute__((packed)) branch64 {
uint16_t opcode;
uint8_t reg;
uint8_t data[0]; // Used to chain instructions together.
};
// Convenient representation of an x64 MOVABS r64, imm64 instruction.
struct __attribute__((packed)) mov_r64_abs_insn {
uint8_t opcode;
uint8_t reg;
union {
uintptr_t i;
void *p;
} imm;
uint8_t data[0]; // Used to chain instructions together.
};

typedef struct mov_r64_abs_insn mov_r64_abs_insn;
#endif

#define X86_64_OPCODE_MOV_ABS_R32 0x48
#define X86_64_OPCODE_MOV_ABS_R64 0x49

#define X86_OPCODE_CALL_NEAR 0xE8
#define X86_64_OPCODE_CALL_REG 0xFF41
#define X86_OPCODE_JMP_NEAR 0xE9
#define X86_64_OPCODE_JMP_NEAR 0xE9

#define X86_OPCODE_NOP 0x90
#define X86_OPCODE_RET 0xC3
#define X86_OPCODE_MOV_EAX_IMM 0xB8
#define X86_OPCODE_PUSH_EBP 0x55
#define X86_OPCODE_NOP 0x90
#define X86_OPCODE_RET 0xC3
#define X86_OPCODE_MOV_EAX_IMM 0xB8
#define X86_OPCODE_PUSH_EBP 0x55
#define X86_64_OPCODE_PUSH_RBP 0x55

#define X86_PREFIX_DATA16 0x66
#define X86_PREFIX_DATA16 0x66

// This is used to save an arbitrary 2 byte integer in the instuction stream
// without disrupting disassemblers.
Expand Down
1 change: 0 additions & 1 deletion intercept/libdis.h

This file was deleted.

7 changes: 0 additions & 7 deletions intercept/libdisasm/AUTHORS

This file was deleted.

Loading