添加项目文件。

This commit is contained in:
Huoji's
2025-07-13 16:23:35 +08:00
parent 9f28a877ef
commit 5eccbbb5e5
9 changed files with 764 additions and 0 deletions

31
sleep_duck.sln Normal file
View File

@@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.35731.53
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sleep_duck", "sleep_duck\sleep_duck.vcxproj", "{8A01CC2B-278C-411F-BEB7-286DC920E493}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{8A01CC2B-278C-411F-BEB7-286DC920E493}.Debug|x64.ActiveCfg = Debug|x64
{8A01CC2B-278C-411F-BEB7-286DC920E493}.Debug|x64.Build.0 = Debug|x64
{8A01CC2B-278C-411F-BEB7-286DC920E493}.Debug|x86.ActiveCfg = Debug|Win32
{8A01CC2B-278C-411F-BEB7-286DC920E493}.Debug|x86.Build.0 = Debug|Win32
{8A01CC2B-278C-411F-BEB7-286DC920E493}.Release|x64.ActiveCfg = Release|x64
{8A01CC2B-278C-411F-BEB7-286DC920E493}.Release|x64.Build.0 = Release|x64
{8A01CC2B-278C-411F-BEB7-286DC920E493}.Release|x86.ActiveCfg = Release|Win32
{8A01CC2B-278C-411F-BEB7-286DC920E493}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {52DFFDE6-0BC8-468E-8698-A824D5F47E90}
EndGlobalSection
EndGlobal

24
sleep_duck/head.h Normal file
View File

@@ -0,0 +1,24 @@
#pragma once
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <windows.h>
#include <psapi.h>
#include <shlwapi.h>
#include <string.h>
#include <wchar.h>
#include <dbghelp.h>
#include <vector>
#include <string>
#pragma comment(lib, "dbghelp.lib")
#include "tlhelp32.h"
#include "include/capstone/capstone.h"
#include "include/capstone/x86.h"
#include <optional>
#pragma comment(lib, "capstone64.lib")
#include "tools.h"
#include "stack_tracker.h"

210
sleep_duck/sleep_duck.cpp Normal file
View File

@@ -0,0 +1,210 @@
#include "head.h"
auto PrintProcessInfoFromHandle(HANDLE hProcess) -> void {
DWORD pid = GetProcessId(hProcess);
DWORD bufferSize = MAX_PATH;
std::vector<wchar_t> pathBuffer(bufferSize);
if (!QueryFullProcessImageNameW(hProcess, 0, pathBuffer.data(),
&bufferSize)) {
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
pathBuffer.resize(bufferSize);
if (!QueryFullProcessImageNameW(hProcess, 0, pathBuffer.data(),
&bufferSize)) {
throw std::runtime_error(
"Failed to query process image name on second attempt. "
"Error code: " +
std::to_string(GetLastError()));
}
} else {
throw std::runtime_error(
"Failed to query process image name. Error code: " +
std::to_string(GetLastError()));
}
}
std::wstring processPath(pathBuffer.data(), bufferSize);
printf("target process %d -> %ws \n", pid, pathBuffer.data());
}
auto SimpleCheckIn2020(HANDLE hProcess, uint64_t Address) -> bool {
MEMORY_BASIC_INFORMATION mbi = {0};
SIZE_T ReadNum = 0;
bool detect = false;
do {
if (VirtualQueryEx(hProcess, (PVOID)Address, &mbi, sizeof(mbi)) ==
false) {
break;
}
if (mbi.Type == MEM_IMAGE) {
break;
}
bool CheckExcuteFlag = mbi.AllocationProtect & PAGE_EXECUTE ||
mbi.AllocationProtect & PAGE_EXECUTE_READ ||
mbi.AllocationProtect & PAGE_EXECUTE_READWRITE ||
mbi.AllocationProtect & PAGE_EXECUTE_WRITECOPY;
if (CheckExcuteFlag) {
printf("rwx memory detect-> \n\t");
PrintProcessInfoFromHandle(hProcess);
detect = true;
char PEStack[0x2];
if (ReadProcessMemory(hProcess, mbi.BaseAddress, PEStack,
sizeof(PEStack), &ReadNum)) {
if (PEStack[0] == 'M' && PEStack[1] == 'Z') {
printf("rwx memory has pe module-> \n\t");
PrintProcessInfoFromHandle(hProcess);
}
}
} else if (mbi.AllocationProtect & PAGE_READONLY ||
mbi.AllocationProtect & PAGE_READWRITE ||
mbi.AllocationProtect & PAGE_NOACCESS) {
printf("no-excute-page detect at %p \n\t", Address);
PrintProcessInfoFromHandle(hProcess);
detect = true;
}
} while (false);
return detect;
}
auto DoCFTrackX64(HANDLE hProcess,
std::vector<std::pair<uint64_t, uint64_t>>& stackArrays)
-> void {
for (size_t i = stackArrays.size() - 1; i > 0; i--) {
auto ripAddr = stackArrays[i].first;
auto retAddr = stackArrays[i].second;
//printf("stack walk: %p\n", ripAddr);
if (retAddr == 0) {
continue;
}
auto rawAddress = ripAddr - 0x16;
StackTracker stackTrack(hProcess, rawAddress, 0x30, false);
if (stackTrack.TryFindValidDisasm(rawAddress, 0x30) == false) {
printf("\nSleepMask Encryption Memory Detected: %p\n\t", rawAddress);
PrintProcessInfoFromHandle(hProcess);
continue;
}
auto [successTrack, nextJmpAddress] = stackTrack.CalcNextJmpAddress();
if (successTrack == false &&
stackTrack.feature != _features::kCallRip &&
stackTrack.feature != _features::kCallReg &&
stackTrack.feature != _features::kSyscall) {
printf("\nNon-integrity Stack Detect: %p\n\t", rawAddress);
PrintProcessInfoFromHandle(hProcess);
break;
}
}
return;
}
auto DoX64StackDetect(HANDLE hProcess, HANDLE hThread) -> void {
STACKFRAME64 StackFarmeEx = {};
CONTEXT context = {0};
context.ContextFlags = CONTEXT_ALL;
std::vector<std::pair<uint64_t, uint64_t>> stackArrays;
SymInitialize(hProcess, nullptr, TRUE);
//printf("scan tid: %d \n", GetThreadId(hThread));
do {
if (GetThreadContext(hThread, &context) == false) {
break;
}
StackFarmeEx.AddrPC.Offset = context.Rip;
StackFarmeEx.AddrPC.Mode = AddrModeFlat;
StackFarmeEx.AddrStack.Offset = context.Rsp;
StackFarmeEx.AddrStack.Mode = AddrModeFlat;
StackFarmeEx.AddrFrame.Offset = context.Rsp;
StackFarmeEx.AddrFrame.Mode = AddrModeFlat;
bool detect = false;
while (true) {
if (StackWalk64(IMAGE_FILE_MACHINE_AMD64, hProcess, hThread,
&StackFarmeEx, &context, NULL,
SymFunctionTableAccess, SymGetModuleBase,
NULL) == false) {
break;
}
if (StackFarmeEx.AddrFrame.Offset == 0) {
break;
}
if (SimpleCheckIn2020(hProcess, StackFarmeEx.AddrPC.Offset)) {
detect = true;
//break;
}
stackArrays.push_back(
{StackFarmeEx.AddrPC.Offset, StackFarmeEx.AddrReturn.Offset});
}
//if (detect) {
// break;
//}
DoCFTrackX64(hProcess, stackArrays);
} while (false);
SymCleanup(hProcess);
}
// 主扫描函数
auto DoLittleHackerMemeDetect(DWORD pidFilter = 0, bool scanAll = false) -> void {
HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); // 所有线程
THREADENTRY32 te32 = {};
te32.dwSize = sizeof(THREADENTRY32);
if (hThreadSnap == INVALID_HANDLE_VALUE || !Thread32First(hThreadSnap, &te32))
return;
do {
// 跳过当前线程
if (te32.th32OwnerProcessID == GetCurrentProcessId() &&
te32.th32ThreadID == GetCurrentThreadId())
continue;
// 判断是否过滤进程
if (!scanAll && pidFilter != 0 && te32.th32OwnerProcessID != pidFilter)
continue;
if (!scanAll && pidFilter == 0 && te32.th32OwnerProcessID != GetCurrentProcessId())
continue;
auto handleDeleter = [](HANDLE h) {
if (h && h != INVALID_HANDLE_VALUE) CloseHandle(h);
};
std::unique_ptr<void, decltype(handleDeleter)> hThread(
OpenThread(THREAD_ALL_ACCESS, FALSE, te32.th32ThreadID),
handleDeleter);
std::unique_ptr<void, decltype(handleDeleter)> hProcess(
OpenProcess(PROCESS_ALL_ACCESS, FALSE, te32.th32OwnerProcessID),
handleDeleter);
if (!hProcess || hProcess.get() == INVALID_HANDLE_VALUE ||
!hThread || hThread.get() == INVALID_HANDLE_VALUE)
continue;
if (!Tools::Is64BitPorcess(hProcess.get()))
continue;
DoX64StackDetect(hProcess.get(), hThread.get());
} while (Thread32Next(hThreadSnap, &te32));
CloseHandle(hThreadSnap);
}
int main(int argc, char* argv[]) {
bool scanAll = true;
DWORD targetPid = 0;
for (int i = 1; i < argc; ++i) {
std::string arg = argv[i];
if (arg == "-all") {
scanAll = true;
}
else if (arg == "-pid" && i + 1 < argc) {
scanAll = false;
targetPid = static_cast<DWORD>(std::stoul(argv[++i]));
}
else {
std::cerr << "[!] Unknown argument ,go scan all: " << arg << "\n";
scanAll = true;
}
}
DoLittleHackerMemeDetect(targetPid, scanAll);
return 0;
}

View File

@@ -0,0 +1,161 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{8a01cc2b-278c-411f-beb7-286dc920e493}</ProjectGuid>
<RootNamespace>sleepduck</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<LibraryPath>F:\project\white_patch_detect\white_patch_detect\libs;$(LibraryPath)</LibraryPath>
<IncludePath>F:\project\white_patch_detect\white_patch_detect\capstone-master;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>F:\project\white_patch_detect\white_patch_detect\capstone-master;$(IncludePath)</IncludePath>
<LibraryPath>F:\project\white_patch_detect\white_patch_detect\libs;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpplatest</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpplatest</LanguageStandard>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="sleep_duck.cpp" />
<ClCompile Include="stack_tracker.cpp" />
<ClCompile Include="tools.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="head.h" />
<ClInclude Include="stack_tracker.h" />
<ClInclude Include="tools.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="源文件">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="头文件">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="资源文件">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="sleep_duck.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="tools.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="stack_tracker.cpp">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="tools.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="head.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="stack_tracker.h">
<Filter>头文件</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,231 @@
#include "stack_tracker.h"
auto StackTracker::rpm(uintptr_t address, size_t readSize)
-> std::vector<char> {
size_t NumOfRead = 0;
std::vector<char> buffer(readSize);
if (ReadProcessMemory(this->targetProcess, (LPCVOID)address, buffer.data(),
readSize, &NumOfRead) == false ||
NumOfRead != readSize) {
return {};
}
return buffer;
}
auto StackTracker::LookslikeValidEntry(cs_insn* insn, size_t count) -> bool {
if (insn == nullptr || count == 0)
return false;
int threshold_score = 2;
int score = 0;
// 限制最多检查前几条指令
size_t check_limit = min(count, static_cast<size_t>(8));
for (size_t i = 0; i < check_limit; ++i) {
const cs_insn& inst = insn[i];
switch (inst.id) {
case X86_INS_PUSH:
if (strcmp(inst.mnemonic, "push") == 0)
score++;
break;
case X86_INS_MOV:
if (strstr(inst.op_str, "rbp") != nullptr || strstr(inst.op_str, "rsp") != nullptr)
score++;
break;
case X86_INS_SUB:
case X86_INS_ADD:
if (strstr(inst.op_str, "rsp") != nullptr)
score++;
break;
case X86_INS_CALL:
score += 1;
break;
case X86_INS_LEA:
if (strstr(inst.op_str, "rip") != nullptr)
score++;
break;
case X86_INS_TEST:
case X86_INS_CMP:
case X86_INS_JE:
case X86_INS_JNE:
case X86_INS_JMP:
score++;
break;
case X86_INS_NOP:
break; // 忽略
default:
if (score == 0)
score -= 1; //杂指令降低一点分数
break;
}
if (score >= threshold_score) {
return true;
}
}
return score >= threshold_score;
}
auto StackTracker::TryFindValidDisasm(uint64_t baseAddr, size_t maxOffset) -> bool {
for (size_t i = 0; i < maxOffset; ++i) {
auto buf = this->rpm(baseAddr + i, this->trackSize);
if (buf.size() != this->trackSize) continue;
cs_insn* testInsn = nullptr;
auto cnt = cs_disasm(this->capstoneHandle,
reinterpret_cast<const uint8_t*>(buf.data()),
this->trackSize, baseAddr + i, 0, &testInsn);
if (cnt > 0 && LookslikeValidEntry(testInsn, cnt)) {
this->baseAddr += i;
if (this->insn != nullptr) {
cs_free(this->insn, this->disasmCount);
}
this->insn = testInsn;
this->disasmCount = cnt;
for (size_t j = 0; j < cnt; ++j) {
this->insList.push_back(std::make_shared<cs_insn>(this->insn[j]));
}
this->readSuccess = true;
return true;
}
}
return false;
}
StackTracker::StackTracker(HANDLE hProcess, uint64_t StartAddress,
size_t trackSize, bool isX32) {
this->isWow64 = isX32;
this->targetProcess = hProcess;
this->baseAddr = StartAddress;
this->trackSize = trackSize;
if (cs_open(CS_ARCH_X86, this->isWow64 ? CS_MODE_32 : CS_MODE_64,
&capstoneHandle) != CS_ERR_OK) {
__debugbreak();
}
cs_option(capstoneHandle, CS_OPT_DETAIL, CS_OPT_ON);
cs_option(capstoneHandle, CS_OPT_SKIPDATA, CS_OPT_ON);
/*
do {
auto bufferArrays = this->rpm(StartAddress, trackSize);
if (bufferArrays.size() != trackSize) {
break;
}
disasmCount =
cs_disasm(capstoneHandle,
reinterpret_cast<const uint8_t*>(bufferArrays.data()),
trackSize, StartAddress, 0, &insn);
if (disasmCount == 0) {
break;
}
for (size_t index = 0; index < disasmCount; index++) {
const auto code = insn[index];
this->insList.push_back(std::make_shared<cs_insn>(code));
}
this->readSuccess = true;
} while (false);
*/
}
auto StackTracker::getNextIns() -> std::shared_ptr<cs_insn> {
if (this->ins_ip >= this->insList.size()) {
return nullptr;
}
const auto result = this->insList[this->ins_ip];
this->ins_ip++;
this->ins_ip_address = result->address;
return result;
}
StackTracker::~StackTracker() {
if (insn) {
cs_free(insn, disasmCount);
cs_close(&capstoneHandle);
}
}
template <typename T, typename B>
auto StackTracker::matchCode(
T match_fn, B process_fn, std::optional<uint32_t> num_operands,
std::vector<std::optional<x86_op_type>> operand_types) -> bool {
while (auto instruction = getNextIns()) {
if (&process_fn != nullptr) {
process_fn(instruction.get());
}
if (num_operands) {
if (instruction->detail->x86.op_count != *num_operands) continue;
bool operand_type_mismatch = false;
for (uint32_t i = 0; i < *num_operands; i++) {
auto& target_type = operand_types[i];
if (target_type &&
target_type != instruction->detail->x86.operands[i].type) {
operand_type_mismatch = true;
break;
}
}
if (operand_type_mismatch) continue;
}
if (match_fn(instruction.get())) return true;
}
return false;
}
inline auto StackTracker::is_call(cs_insn* ins) -> bool {
return ins->id == X86_INS_CALL;
}
auto StackTracker::CalcNextJmpAddress() -> std::pair<bool, uint64_t> {
if (this->readSuccess == false) {
return {false , 0};
}
this->feature = _features::kNonCallOnly;
uint64_t callAddress = 0;
auto isMatchCall = matchCode(
[&](cs_insn* instruction) {
if (instruction->id != X86_INS_CALL) {
if (instruction->id == X86_INS_SYSCALL) {
this->feature = _features::kSyscall;
}
return false;
}
if (instruction->detail->x86.op_count != 1) {
return false;
}
const cs_x86_op& operand = instruction->detail->x86.operands[0];
if (operand.type == X86_OP_IMM) {
callAddress =
instruction->address + instruction->size + operand.imm;
return true;
}
else if (operand.type == X86_OP_MEM) {
const x86_op_mem& mem = operand.mem;
// 我们只处理可以静态计算的 RIP 相对寻址
if (mem.base == X86_REG_RIP) {
uint64_t pointerAddress = instruction->address + instruction->size + mem.disp;
size_t pointerSize = this->isWow64 ? 4 : 8;
std::vector<char> pointerBuffer = this->rpm(pointerAddress, pointerSize);
if (pointerBuffer.empty()) {
std::cerr << "Failed to read pointer at 0x" << std::hex << pointerAddress << std::endl;
return false;
}
if (pointerSize == 8) {
callAddress = *reinterpret_cast<uint64_t*>(pointerBuffer.data());
}
else { // 32位
callAddress = *reinterpret_cast<uint32_t*>(pointerBuffer.data());
}
//std::cout << "Found RIP-relative call at 0x" << std::hex << instruction->address
// << ". Pointer at 0x" << pointerAddress
// << ". Final Target: 0x" << callAddress << std::endl;
return true;
}
//std::cout << "Skipping non-RIP-relative memory call at 0x" << std::hex << instruction->address << std::endl;
this->feature = _features::kCallRip;
return false;
}
else if (operand.type == X86_OP_REG) {
this->feature = _features::kCallReg;
return false;
}
return false;
},
[&](cs_insn* instruction) {}, {}, {});
return {isMatchCall, callAddress};
}

View File

@@ -0,0 +1,39 @@
#pragma once
#include "head.h"
enum class _features {
kNone,
kNonCallOnly,
kCallRip,
kCallReg,
kSyscall
};
class StackTracker {
private:
bool readSuccess;
bool isWow64;
HANDLE targetProcess;
std::vector<std::shared_ptr<cs_insn>> insList;
cs_insn* insn = nullptr;
size_t disasmCount = 0;
csh capstoneHandle;
uint64_t ins_ip, ins_ip_address, baseAddr, trackSize;
auto getNextIns() -> std::shared_ptr<cs_insn>;
auto LookslikeValidEntry(cs_insn* insn, size_t count) -> bool;
inline auto is_call(cs_insn* ins) -> bool;
template <typename T, typename B>
auto matchCode(T match_fn, B process_fn,
std::optional<uint32_t> num_operands,
std::vector<std::optional<x86_op_type>> operand_types)
-> bool;
auto rpm(uintptr_t address, size_t readSize) -> std::vector<char>;
public:
_features feature;
StackTracker(HANDLE hProcess, uint64_t StartAddress, size_t trackSize,
bool isX32);
~StackTracker();
auto CalcNextJmpAddress() -> std::pair<bool, uint64_t>;
auto TryFindValidDisasm(uint64_t baseAddr, size_t maxOffset) -> bool;
};

23
sleep_duck/tools.cpp Normal file
View File

@@ -0,0 +1,23 @@
#include "tools.h"
namespace Tools {
auto Is64BitPorcess(HANDLE hProcess) -> bool {
BOOL bIsWow64 = false;
IsWow64Process(hProcess, &bIsWow64);
return bIsWow64 == false;
}
auto EnableDebugPrivilege(bool bEnable) -> bool {
bool fOK = FALSE; // Assume function fails
HANDLE hToken;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES,
&hToken)) {
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = 1;
LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);
tp.Privileges[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED : 0;
AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL);
fOK = (GetLastError() == ERROR_SUCCESS);
CloseHandle(hToken);
}
return fOK;
}
}; // namespace Tools

6
sleep_duck/tools.h Normal file
View File

@@ -0,0 +1,6 @@
#pragma once
#include "head.h"
namespace Tools {
auto EnableDebugPrivilege(bool bEnable) -> bool;
auto Is64BitPorcess(HANDLE hProcess) -> bool;
};