截取系统API调用

VB编程中截取键盘输入的实践指南 API(Application Programming Interface)是一组预定义的函数、协议和工具,用于构建软件应用程序。API函数可以是系统提供的标准函数,也可以是第三方库提供的特定功能函数。在VB(Visual Basic)中,API函数用于扩展语言的功能,允许程序员访问操作系统级别的服务和硬件资源,实现更复杂的操作和处理。在现代软件开发中,能够实时监控用户的键盘输入是一项非常重要的功能,尤其在游戏开发、安全监测以及辅助工具等领域。在诸多可用的技术中,函数因其高效性和实用性脱颖而出。 阅读详情
 
在很多情况下,为了测试代码或扩展操作系统的功能,软件开发人员或测试人员必须截取系统函数调用。有一些软件包能够提供该功能,如微软公司的 Detours* 库,或 OK Thinking Software 的 Syringe*。但是从另一个角度而言,开发人员可能希望不需借助第三方软件,自己就能实现该功能。

本文描述了函数截取的几种不同方式,并详细介绍了无需使用商业软件包,也不需受 GNU*(通用公共许可证)许可的约束,就能够实现该功能的一种通用方法。本文所有材料由英特尔公司开发,或根据 MSDN* 样本代码修改而来。

截取系统函数调用的两项基本技术
大部分截取任意函数调用的方法都是准备一个 DLL,用来替代将被截取的目标函数,然后将 DLL 注入至目标进程;在与目标进程连接的基础上,DLL 将自己与目标函数相连。这种技术之所以适合此任务,是因为在大多数情况下我们无法获得目标应用程序的源代码,而这种技术只需相对简单地编写一个包含代换函数的 DLL,就可将其与软件的其它部分分离开来。

两种截取方法已经过研究和分析。Syringe 通过修改函数输入条目(thunking 表)运行。而Detours 库则直接修改目标函数(在目标进程空间内),并无条件地跳转至代换函数。此外,它还提供能够调用原始函数的 trampoline 函数。

Detours 技术之所以采用后一种方法,是因为在许多情况下,Syringe 无法找到 thunk,并且它不能提供 trampoline功能来调用原始函数。在这两种方法下,注入 DLL 的工作方式相同。

截取系统函数调用的全部工作流程如下所示:


1.DLL 注入 — 首先,主软件打开目标进程,并使其加载包含代换函数的 DLL。


2.目标函数修改 — 当 DLL 连接至进程时,它在目标进程空间内修改目标函数,从而直接跳转至 DLL 中的代换函数。Trampoline 函数能够随意调用原始函数。


3.目标函数截取 — 当调用目标函数时,它直接跳转至 DLL 中的代换函数。如果开发人员希望调用原始的功能,则他或她就可以调用 trampoline 函数。


DLL 注入
本节内容完全以 MSDN 文章“定制调试诊断工具和实用程序 — 摆脱 DLL“地狱” (DLL Hell)*”为基础,该文章还包括可下载的源代码。在本文附录中可获得 Inject.cpp 和 Inject.h 。已对它们进行了定制以便于集成——仅需将其包括在项目中然后调用 InjectLib 即可。使目标进程加载 DLL 的算法按如下步骤工作:


1.通过调用 OpenProcess 打开目标进程。


2.通过调用 VirtualAllocEx 在目标进程中分配内存。利用 WriteProcessMemory 将要被注入的 DLL 名称写入分配的内存。


3.通过调用 GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryW") 来获取 LoadLibrary 的地址;


4.调用 CreateRemoteThread,指定 LoadLibrary 的入口点,并将 DLL (第 2 步中) 的名称作为其自变量。目标进程将加载 DLL。


5.利用 VirtualFreeEx 释放分配的内存。已不再需要该内存。



Inject.cpp 融合了包括稳固的安全特性等大量其它功能,但上述步骤已足够阐明其核心概念。

目标函数修改
目标函数修改为自我修改代码,尽管在将 jmp 注入进程内存的过程中存在一些缺陷,但它在 MSDN* 上具有完善的文件证明。为避免混淆,本节列出了几乎全部的样本代码。

目标函数修改的两个主要方面为代换函数和 trampoline 函数。下面的代码片断为截取 GetSystemPowerStatus API 的 DLL 示例:
这段代码为连接所做的第一件事就是调用 InterceptAPI。需要使用包含目标函数的模块名称、目标函数的名称以及代换函数的地址。 GetSystemPowerStatus 位于 kernel32.dll 中。其它基本的 Win32* API,如 MessageBox 和 PeekMessage,都能够在 user32.dll 中获得。MSDN 指定每个 API 所属的模块;未来的增强版中,将自动为给定的 API 找到正确的模块。

InterceptAPI 将目标函数的前五个字节覆盖为无条件跳转(opcode 0xE9),后面为四个字节的带符号整数(向代换函数的位移)。位移从下一个指令开始;因此需要使用 pbReplaced - (pbTargetCode +4)。进行该代码操作时,需要注意以下两点:


1.将区域覆盖的保护模式改为 VirtualProtect。否则,将发生非法访问错误。


2.必须使用 FlushInstructionCache 来支持指令已存在于高速缓存中的情况。否则,即使内存中的指令已经有所变化,旧代码仍将在高速缓存中运行。


现在,当调用 GetSystemPowerStatus 函数时,它跳转至代换函数,然后直接返回调用方,成功截取调用。


Trampoline 函数
在很多情况下,代换函数除使用自身代码外,还需调用原始目标函数,这样就能够扩展 API 的功能,而不是替换整个 API。Trampoline 函数可以提供该功能。Trampoline 函数的原理如下所示:


*编写一个具有相同声明的哑元函数(dummy function),将作为 trampoline 使用。确保哑元函数的长度超过 10 个字节。


*在覆盖目标函数的前五个字节之前,将它们复制到 trampoline 函数的起始处。


*利用无条件跳转,将trampoline的第六个字节覆盖为目标函数的第六个字节。


*与之前一样覆盖目标函数。


*当从代换函数或其它地方调用 trampoline 函数时,它执行复制出的原始代码的前五个字节,然后跳转至实际原始代码的第六个字节。控制返回至 trampoline 的调用方。当完成其它任务时,控制返回至 API 的控制方。


可能存在一种复杂的情况,即原始代码的第六个字节可能是先前指令的一部分。在这种情况下,函数会覆盖部分先前指令,然后崩溃。在 GetSystemPowerStatus 的情况中,前五个字节后的新指令开始于第七个字节。因此,对于这种工作机制,需要将六个字节复制到 trampoline,并且代码必须相应地调整这个偏移量。

代码需要复制的字节数取决于 API。查看原始目标代码(利用调试器或反汇编器)并计算需要复制的字节数是非常必要的。未来的增强版将自动检测正确的偏移量。假设我们已经知道正确的偏移量,下面的代码则显示出可建立 trampoline 函数的可扩展 InterceptAPI 函数:
BOOL InterceptAPI(HMODULE hLocalModule, const char* c_szDllName, const char* c_szApiName,
DWORD dwReplaced, DWORD dwTrampoline, int offset)
{
int i;
DWORD dwOldProtect;
DWORD dwAddressToIntercept = (DWORD)GetProcAddress(
GetModuleHandle((char*)c_szDllName), (char*)c_szApiName);

BYTE *pbTargetCode = (BYTE *) dwAddressToIntercept;
BYTE *pbReplaced = (BYTE *) dwReplaced;
BYTE *pbTrampoline = (BYTE *) dwTrampoline;

// Change the protection of the trampoline region
// so that we can overwrite the first 5 + offset bytes.
VirtualProtect((void *) dwTrampoline, 5+offset, PAGE_WRITECOPY, &dwOldProtect);
for (i=0;i<offset;i++)
*pbTrampoline++ = *pbTargetCode++;
pbTargetCode = (BYTE *) dwAddressToIntercept;

// Insert unconditional jump in the trampoline.
*pbTrampoline++ = 0xE9; // jump rel32
*((signed int *)(pbTrampoline)) = (pbTargetCode+offset) - (pbTrampoline + 4);
VirtualProtect((void *) dwTrampoline, 5+offset, PAGE_EXECUTE, &dwOldProtect);

// Overwrite the first 5 bytes of the target function
VirtualProtect((void *) dwAddressToIntercept, 5, PAGE_WRITECOPY, &dwOldProtect);
*pbTargetCode++ = 0xE9; // jump rel32
*((signed int *)(pbTargetCode)) = pbReplaced - (pbTargetCode +4);
VirtualProtect((void *) dwAddressToIntercept, 5, PAGE_EXECUTE, &dwOldProtect);

// Flush the instruction cache to make sure
// the modified code is executed.
FlushInstructionCache(GetCurrentProcess(), NULL, NULL);
return TRUE;
}

结论
本文描述了截取系统函数调用的一种通用方法,同时还提供了 trampoline 函数,从而保留了原始功能。本文仅对方法进行简要描述,并未对完整的软件包作出说明,因此如下一些细节并没有实现:


1.自动检测包含目标 API 的模块。


2.自动检测 trampoline 函数的偏移量。


3.删除代换函数,并注入 DLL。(到目前为止,清空代换函数的唯一方法是关闭应用程序。)


然而,对于开发人员而言,无需依赖第三方软件包,执行截取任意系统函数调用的软件,本文中涉及的技术、说明及源代码已经足够。

作者介绍

Seung-Woo Kim 拥有明尼苏达大学的计算机科学博士学位,目前为英特尔公司的高级应用工程师。他致力于技术与商业软件的性能优化。可通过此电子邮件地址与他取得联系。
截取系统 API 调用
附录:
#include "stdafx.h"
#include "Inject.h"
#include <tchar.h>
#include <malloc.h> // For alloca
#include <pi.h>
#ifdef UNICODE
#define InjectLib InjectLibW
#else
#define InjectLib InjectLibA
#endif // !UNICODE
BOOL AdjustDacl(HANDLE h, DWORD DesiredAccess)
{
// the WORLD Sid is trivial to form programmatically (S-1-1-0)
SID world = { SID_REVISION, 1, SECURITY_WORLD_SID_AUTHORITY, 0 };

EXPLICIT_ACCESS ea =
{
DesiredAccess,
SET_ACCESS,
NO_INHERITANCE,
{
0, NO_MULTIPLE_TRUSTEE,
TRUSTEE_IS_SID,
TRUSTEE_IS_USER,
reinterpret_cast<LPTSTR>(&world)
}
};
ACL* pdacl = 0;
DWORD err = SetEntriesInAcl(1, &ea, 0, &pdacl);
if (err == ERROR_SUCCESS)
{
err = SetSecurityInfo(h, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, 0, 0, pdacl, 0);
LocalFree(pdacl);
return(err == ERROR_SUCCESS);
}
else
return(FALSE);
}
// Useful helper function for enabling a single privilege
BOOL EnableTokenPrivilege(HANDLE htok, LPCTSTR szPrivilege, TOKEN_PRIVILEGES& tpOld)
{
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = 1;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (LookupPrivilegeValue(0, szPrivilege, &tp.Privileges[0].Luid))
{
// htok must have been opened with the following permissions:
// TOKEN_QUERY (to get the old priv setting)
// TOKEN_ADJUST_PRIVILEGES (to adjust the priv)
DWORD cbOld = sizeof tpOld;
if (AdjustTokenPrivileges(htok, FALSE, &tp, cbOld, &tpOld, &cbOld))
// Note that AdjustTokenPrivileges may succeed, and yet
// some privileges weren't actually adjusted.
// You've got to check GetLastError() to be sure!
return(ERROR_NOT_ALL_ASSIGNED != GetLastError());
else
return(FALSE);
}
else
return(FALSE);
}

// Corresponding restoration helper function
BOOL RestoreTokenPrivilege(HANDLE htok, const TOKEN_PRIVILEGES& tpOld)
{
return(AdjustTokenPrivileges(htok, FALSE, const_cast<TOKEN_PRIVILEGES*>(&tpOld), 0, 0, 0));
}
HANDLE GetProcessHandleWithEnoughRights(DWORD PID, DWORD AccessRights)
{
HANDLE hProcess = ::OpenProcess(AccessRights, FALSE, PID);
if (hProcess == NULL)
{
HANDLE hpWriteDAC = OpenProcess(WRITE_DAC, FALSE, PID);
if (hpWriteDAC == NULL)
{
// hmm, we don't have permissions to modify the DACL...
// time to take ownership...
HANDLE htok;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &htok))
return(FALSE);

TOKEN_PRIVILEGES tpOld;
if (EnableTokenPrivilege(htok, SE_TAKE_OWNERSHIP_NAME, tpOld))
{
// SeTakeOwnershipPrivilege allows us to open objects with
// WRITE_OWNER, but that's about it, so we'll update the owner,
// and dup the handle so we can get WRITE_DAC permissions.
HANDLE hpWriteOwner = OpenProcess(WRITE_OWNER, FALSE, PID);
if (hpWriteOwner != NULL)
{
BYTE buf[512]; // this should always be big enough
DWORD cb = sizeof buf;
if (GetTokenInformation(htok, TokenUser, buf, cb, &cb))
{
DWORD err =
SetSecurityInfo(
hpWriteOwner,
SE_KERNEL_OBJECT,
OWNER_SECURITY_INFORMATION,
reinterpret_cast<TOKEN_USER*>(buf)->User.Sid,
0, 0, 0
);
if (err == ERROR_SUCCESS)
{
// now that we're the owner, we've implicitly got WRITE_DAC
// permissions, so ask the system to reevaluate our request,
// giving us a handle with WRITE_DAC permissions
if (
!DuplicateHandle(
GetCurrentProcess(),
hpWriteOwner,
GetCurrentProcess(),
&hpWriteDAC,
WRITE_DAC, FALSE, 0
)
)
hpWriteDAC = NULL;
}
}

// don't forget to close handle
::CloseHandle(hpWriteOwner);
}

// not truly necessary in this app,
// but included for completeness
RestoreTokenPrivilege(htok, tpOld);
}

// don't forget to close the token handle
::CloseHandle(htok);
}

if (hpWriteDAC)
{
// we've now got a handle that allows us WRITE_DAC permission
AdjustDacl(hpWriteDAC, AccessRights);

// now that we've granted ourselves permission to access
// the process, ask the system to reevaluate our request,
// giving us a handle with right permissions
if (
!DuplicateHandle(
GetCurrentProcess(),
hpWriteDAC,
GetCurrentProcess(),
&hProcess,
AccessRights,
FALSE,
0
)
)
hProcess = NULL;

CloseHandle(hpWriteDAC);
}
}

return(hProcess);
}
BOOL WINAPI InjectLibW(DWORD dwProcessId, PCWSTR pszLibFile)
{
BOOL fOk = FALSE; // Assume that the function fails
HANDLE hProcess = NULL, hThread = NULL;
PWSTR pszLibFileRemote = NULL;

// Get a handle for the target process.
hProcess =
GetProcessHandleWithEnoughRights(
dwProcessId,
PROCESS_QUERY_INFORMATION | // Required by Alpha
PROCESS_CREATE_THREAD | // For CreateRemoteThread
PROCESS_VM_OPERATION | // For VirtualAllocEx/VirtualFreeEx
PROCESS_VM_WRITE // For WriteProcessMemory
);
if (hProcess == NULL)
return(FALSE);

// Calculate the number of bytes needed for the DLL's pathname
int cch = 1 + lstrlenW(pszLibFile);
int cb = cch * sizeof(WCHAR);

// Allocate space in the remote process for the pathname
pszLibFileRemote =
(PWSTR) VirtualAllocEx(hProcess, NULL, cb, MEM_COMMIT, PAGE_READWRITE);

if (pszLibFileRemote != NULL)
{
// Copy the DLL's pathname to the remote process's address space
if (WriteProcessMemory(hProcess, pszLibFileRemote,
(PVOID) pszLibFile, cb, NULL))
{
// Get the real address of LoadLibraryW in Kernel32.dll
PTHREAD_START_ROUTINE pfnThreadRtn = (PTHREAD_START_ROUTINE)
GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryW");
if (pfnThreadRtn != NULL)
{
// Create a remote thread that calls LoadLibraryW(DLLPathname)
hThread = CreateRemoteThread(hProcess, NULL, 0,
pfnThreadRtn, pszLibFileRemote, 0, NULL);
if (hThread != NULL)
{
// Wait for the remote thread to terminate
WaitForSingleObject(hThread, INFINITE);

fOk = TRUE; // Everything executed successfully

CloseHandle(hThread);
}
}
}
// Free the remote memory that contained the DLL's pathname
VirtualFreeEx(hProcess, pszLibFileRemote, 0, MEM_RELEASE);
}

CloseHandle(hProcess);

return(fOk);
}

BOOL WINAPI InjectLibA(DWORD dwProcessId, PCSTR pszLibFile) {

// Allocate a (stack) buffer for the Unicode version of the pathname
PWSTR pszLibFileW = (PWSTR)
_alloca((lstrlenA(pszLibFile) + 1) * sizeof(WCHAR));

// Convert the ANSI pathname to its Unicode equivalent
wsprintfW(pszLibFileW, L"%S", pszLibFile);

// Call the Unicode version of the function to actually do the work.
return(InjectLibW(dwProcessId, pszLibFileW));
}
VB封包截取工具源代码解析 WinPCap由三个主要的组件构成:网络驱动、底层动态链接库和高层API。该库能够捕获数据包,并可以绕过操作系统的限制,直接从网卡上读取封包,这为网络监听、监控提供了高效的方式。WinPCap库的功能强大,特点鲜明:实时捕获:支持实时捕获网络封包,不受操作系统的限制。发送封包:允许用户构造封包并发送到网络上。封包过滤器:提供一个强大的封包过滤器,可以根据多种条件筛选封包。性能优化:优化的数据包读取速度和低资源占用。 阅读详情

相关推荐

matianl:SAP 最详细的权限管理解析

上文所说的系统自带权限对象与权限字段仅能满足有限的需要,其权限审核的逻辑也是系统硬编码了的,我们能做的只是是否启用某项权限对象的检查(使用SU22)。如果需要自定义,通过SU20、SU21定义即可。

matinal 當冬夜漸暖 。公众号:matinal 2155

Windows代码实现禁用和启用安全模式

实现比较简单,是通过修改注册表:HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/SafeBoot的子项Minimal和Network的名字实现的。 1、提权 CAccessToken token; token.GetProcessToken(TOKEN_ALL_ACCESS); token.EnablePrivilege(SE_TAK...

tansh4731的专栏 2154

手把手教你逆向分析某里系bx-ua参数(以225版本为例)

本文详细解析了某里系应用bx-ua参数的逆向工程实战方法,重点拆解其三层加密体系(二进制加密、字符替换和Base64编码)。通过工具链配置和实战案例,帮助开发者掌握逆向分析技巧,适用于合法合规的安全研究和加密技术评估场景。

weixin_33220360的博客 414

TakeOwnership

#include #include //Forward declaration of SetPrivilege BOOL SetPrivilege( HANDLE hToken, // access token handle LPCTSTR lpszPrivilege, // name of privilege to enable/disable

tiandyoin的专栏 1841

手把手教你用UM982搭建厘米级RTK定位系统(附避坑指南)

本文详细介绍了如何使用UM982模组搭建厘米级RTK定位系统,涵盖硬件连接、软件配置和深度优化技巧。UM982支持BDS、GPS、GLONASS和Galileo等多系统全频点信号,特别适合精准农业、无人机导航等高精度应用场景。通过实战案例和避坑指南,帮助开发者快速实现厘米级定位精度。

y7z8a的博客 1444

【VisualStdio】手把手教你做一个上位机(1)控件设计布局

网上有很多形形色色的制作上位机教程,有些写的挺好的,但是过于单调。

m0_73409202的博客 5441

修改 Windows 文件访问权限的多种方法

由于文件是安全对象,因此访问它们受访问控制模型控制,该模型控制对 Windows 中所有其他安全对象的访问。更改文件或目录对象的安全描述符,需要调用或等函数。ACL,用来表示用户(组)权限的列表,包括 DACL和 SACL;ACE,ACL中的元素;DACL,用来表示安全对象权限的列表;SACL,用来记录对安全对象访问的日志。关于这几个概念已经有很多资料解释,这里就不详细展开了。(以下仅介绍通过Win32API修改文件安全属性的一些内容)。

溡漪幽博客 1万+

数据分析——员工离职预测

员工离职预测一. 题目描述二. 数据说明三. 步骤实现1.导入并查看2.数据探索性分析3.数据处理4.模型分析5.结果分析(1) 可视化的结果分析(2)特征选择结果分析(3)多模型交叉验证结果分析 一. 题目描述 员工是否准备离职是困扰用人单位的问题,其关系到单位业务的开展及新人员的招聘,及时的分析出有离职倾向的员工成为关键的因素。数据主要包括影响员工离职的各种因素(工资、出差、工作环境满意度、工作投入度、是否加班、是否升职、工资提升比例等)以及员工是否已经离职的对应记录。 二. 数据说明 数据分为训练数据

weixin_43925467的博客 1万+

关于获取文件管理员操作权限的函数

BOOL TakeOwnership(LPTSTR lpszOwnFile) <br />{<br /><br />    BOOL bRetval = FALSE;<br /><br />    HANDLE hToken = NULL; <br />    PSID pSIDAdmin = NULL;<br />    PSID pSIDEveryone = NULL;<br />    PACL pACL = NULL;<br />    SID_IDENTIFI

xiaohuaidan717的专栏 766

Outlook邮件备份全攻略:从导出到导入的完整流程(附常见问题解决)

本文提供了一份详尽的Outlook邮件备份全攻略,涵盖从导出到导入的完整流程。重点解析了经典桌面版Outlook的.pst文件备份方法、进阶的智能筛选备份策略,以及如何通过导入恢复和工具验证确保备份可用。同时,文章还介绍了构建自动化备份体系与异地容灾的最佳实践,并附有常见问题解决方案,帮助用户建立可靠的邮件数据安全防线。

weixin_29248611的博客 900

Chromatix_AEC—深入解析曝光表配置与传感器参数计算

本文深入解析高通Chromatix AEC模块中的曝光表配置与传感器参数计算,详细介绍了自动曝光控制(AEC)的核心概念、首行曝光时间计算、行时间与曝光模式对比、帧率计算逻辑以及曝光表高级配置技巧。通过实战案例展示如何优化传感器参数联调,帮助开发者掌握Chromatix工具在摄像头系统中的关键应用。

266

Java-String类常用API:遍历,替换,截取,分割操作

1.public int length():获取字符长度 String name = "我爱你中国love"; System.out.println(name.length); 运行截图: 2.public char charAt(int index):获取某个索引位置处的字符 char ch = name.charAt(1);//获取索引1位置的字符 System.out.println(ch); 运行截图: 3.遍历字符中每个字符的长度 System.out.println(

weixin_52309279的博客 1375

YOLOv11全网首发:注意力独家魔改 | 具有切片操作的SimAM注意力,魔改SimAM助力小目标检测

1)直接作为注意力使用,效果秒杀SimAM;2)高效和卷积结合,代替原始网络的卷积操作;

①答疑群聊服务;②YOLO大模型知识问答系统;③计算机视觉论文生成智能体; 1576

截取系统 API 调用

截取系统 API 调用 在很多情况下,为了测试代码或扩展操作系统的功能,软件开发人员或测试人员必须截取系统函数调用。有一些软件包能够提供该功能,如微软公司的 Detours* 库,或 OK Thinking Software 的 Syringe*。但是从另一个角度而言,开发人员可能希望不需借助第三方软件,自己就能实现该功能。 本文描述了函数截取的几种不同方式,并详细介绍了无需使用商业软

毒行江湖的专栏 1146

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

截取系统 API 调用(转)

在很多情况下,为了测试代码或扩展操作系统的功能,软件开发人员或测试人员必须截取系统函数调用。有一些软件包能够提供该功能,如微软公司的 Detours* 库,或 OK Thinking Software 的 Syringe*。但是从另一个角度而言,开发人员可能希望不需借助第三方软件,自己就能实现该功能。 本文描述了函数截取的几种不同方式,并详细介绍了无需使用商业软件包,也不需受 GNU*(通用...

weixin_33690367的博客 168

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Windows系统调用中API的3环部分

一、R3环API分析的重要性 Windows所提供给R3环的API,实质就是对操作系统接口的封装,其实现部分都是在R0实现的。 很多恶意程序会利用钩子来钩取这些API,从而达到截取内容,修改数据的意图。 现在我们使用olldbg对ReadProcessMemory进行跟踪分析,查看其在R3的实现,并根据我们的分析来重写一个ReadProcessMemory。 重写ReadProcessMe...

dz45693的专栏 2942

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

JNA 调用windows平台截取屏幕

import java.awt.Dimension; import java.awt.Rectangle; import java.awt.Toolkit; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.awt.image.DataBuffer; import java.awt.

LzwGlory的专栏 5840

C# 活动窗体截图:基于 Win32 API 的实现

该截图功能类基于BitBltGDI+user32.dlldwmapi.dllgdi32.dll返回窗口边框矩形(不含阴影等视觉扩展),而能获取实际显示区域,确保截图完整。BitBltBitBlt适用场景与限制BitBlt。

qq_41184334的博客 728

用纯C#实现截取屏幕指定区域

以前在别的地方见过一个通过调用系统API实现屏幕截图的例子,从内心来说我不太喜欢在C#代码中出现这种情况,现在什么都讲“和谐”,我觉得这种做法就是破坏了我们的“和谐”代码,呵呵,开玩笑,有的时候,不通过系统API确实难以做到的。 下面讲述的就是怎么通过纯C#来实现屏幕截图,代码如下: //截取全屏图象privatevoidbtnFullScreen_Click(objectsender,...

caobihole 387

基于Tauri与Rust构建跨平台窗口管理工具:从系统API调用到性能优化

窗口管理是提升多任务处理效率的基础技术,其核心原理在于通过操作系统API获取并控制应用程序窗口的状态与内容。在工程实践中,跨平台窗口枚举、实时缩略图生成与低资源占用是实现高效管理工具的技术难点。通过合理的技术选型与架构设计,开发者可以构建轻量级辅助工具,显著提升工作流效率。本文以Tauri框架结合Rust后端为例,深入探讨了如何利用系统级API实现窗口列表获取、智能截图更新策略及前端性能优化,特别针对Electron应用体积过大与实时截图性能损耗等常见痛点,提供了差异更新与缓存机制等解决方案。该方案适用于需

weixin_30876945的博客 386

一些常用的API--java小白学习

本文介绍了Java中常用的API和集合操作。主要内容包括:1)API的使用方法,如Scanner和Random类;2)String类的特性及常用方法(比较、遍历、截取、替换等);3)StringBuilder类的高效字符串操作;4)ArrayList集合的创建和增删改查操作。文章通过具体代码示例展示了字符串处理、回文判断、集合筛选等常见场景的应用,并比较了不同数据结构的适用场景。最后提供了多个练习案例,帮助掌握字符串和集合的实际应用。

小白博客 942

DELPHI HOOK随手笔记

在 DOS 系统中编程,经常会采取截取中断向量的技术:我们可以设置新的中断服务程序,当系统其他的程序调用这个中断时,就让它先调用我们自己设置的新的中断服务程序,然后再调用原来的中断服务程序,这样就能够获得非凡的控制权。许多优秀的软件和大多数 DOS 病毒程序都采用了这个方法。 在 Windows 中,我们也可以采取类似技术。当系统调用某个 API 函数时,就会先进入我们自己的函数,然后再调用原...

kinvsn的博客 1360

JavaScript 核心 API 详解:数组与字符串的常用方法全解析

本文系统梳理了JavaScript中数组和字符串的核心API,重点区分了是否修改原数据及返回值类型。数组方法分为增删元素、排序、索引查找、转换与截取四类,强调push/pop等会修改原数组,而slice等不会。字符串方法如indexOf则不会改变原字符串。最佳实践包括关注方法副作用、善用返回值、注意字符串不可变性,以及数字排序必须传入回调函数。掌握这些基础API能显著提升开发效率和代码质量。

2602_95057108的博客 369
上一篇: Self-Deleting Executables
下一篇: OFFICE漏洞挂马利用代码
iiprogram
博客等级 码龄25年 1068粉丝 1515原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值