截取系统 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 的工作方式相同。 截取系统函数调用的全部工作流程如下所示:
DLL 注入 — 首先,主软件打开目标进程,并使其加载包含代换函数的 DLL。
目标函数修改 — 当 DLL 连接至进程时,它在目标进程空间内修改目标函数,从而直接跳转至 DLL 中的代换函数。Trampoline 函数能够随意调用原始函数。
目标函数截取 — 当调用目标函数时,它直接跳转至 DLL 中的代换函数。如果开发人员希望调用原始的功能,则他或她就可以调用 trampoline 函数。
DLL 注入
本节内容完全以 MSDN 文章“ 定制调试诊断工具和实用程序 — 摆脱 DLL“地狱”   (DLL Hell)*”为基础,该文章还包括可下载的源代码。在本文附录中可获得 Inject.cpp 和 Inject.h 。已对它们进行了定制以便于集成——仅需将其包括在项目中然后调用 InjectLib 即可。使目标进程加载 DLL 的算法按如下步骤工作:
通过调用 OpenProcess 打开目标进程。
通过调用 VirtualAllocEx 在目标进程中分配内存。利用 WriteProcessMemory 将要被注入的 DLL 名称写入分配的内存。
通过调用 GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryW") 来获取 LoadLibrary 的地址;
调用 CreateRemoteThread,指定 LoadLibrary 的入口点,并将 DLL (第 2 步中) 的名称作为其自变量。目标进程将加载 DLL。
利用 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)。进行该代码操作时,需要注意以下两点:
将区域覆盖的保护模式改为 VirtualProtect。否则,将发生非法访问错误。
必须使用 FlushInstructionCache 来支持指令已存在于高速缓存中的情况。否则,即使内存中的指令已经有所变化,旧代码仍将在高速缓存中运行。
现在,当调用 GetSystemPowerStatus 函数时,它跳转至代换函数,然后直接返回调用方,成功截取调用。
Trampoline 函数
在很多情况下,代换函数除使用自身代码外,还需调用原始目标函数,这样就能够扩展 API 的功能,而不是替换整个 API。Trampoline 函数可以提供该功能。Trampoline 函数的原理如下所示:
编写一个具有相同声明的哑元函数(dummy function),将作为 trampoline 使用。确保哑元函数的长度超过 10 个字节。
在覆盖目标函数的前五个字节之前,将它们复制到 trampoline 函数的起始处。
利用无条件跳转,将trampoline的第六个字节覆盖为目标函数的第六个字节。
与之前一样覆盖目标函数。
当从代换函数或其它地方调用 trampoline 函数时,它执行复制出的原始代码的前五个字节,然后跳转至实际原始代码的第六个字节。控制返回至 trampoline 的调用方。当完成其它任务时,控制返回至 API 的控制方。
可能存在一种复杂的情况,即原始代码的第六个字节可能是先前指令的一部分。在这种情况下,函数会覆盖部分先前指令,然后崩溃。在 GetSystemPowerStatus 的情况中,前五个字节后的新指令开始于第七个字节。因此,对于这种工作机制,需要将六个字节复制到 trampoline,并且代码必须相应地调整这个偏移量。 代码需要复制的字节数取决于 API。查看原始目标代码( 利用调试器或反汇编器)并计算需要复制的字节数是非常必要的。未来的增强版将自动检测正确的偏移量。假设我们已经知道正确的偏移量,下面的代码则显示出可建立 trampoline 函数的可扩展 InterceptAPI 函数:
 1  BOOL InterceptAPI(HMODULE hLocalModule,  const   char *  c_szDllName,  const   char *  c_szApiName,  2          DWORD dwReplaced, DWORD dwTrampoline,  int  offset)  3  {  4       int  i;  5      DWORD dwOldProtect;  6          DWORD dwAddressToIntercept  =  (DWORD)GetProcAddress(  7              GetModuleHandle(( char * )c_szDllName), ( char * )c_szApiName);  8   9      BYTE  * pbTargetCode  =  (BYTE  * ) dwAddressToIntercept; 10      BYTE  * pbReplaced  =  (BYTE  * ) dwReplaced; 11      BYTE  * pbTrampoline  =  (BYTE  * ) dwTrampoline; 12  13       //  Change the protection of the trampoline region 14       //  so that we can overwrite the first 5 + offset bytes. 15      VirtualProtect(( void   * ) dwTrampoline,  5 + offset, PAGE_WRITECOPY,  & dwOldProtect); 16       for  (i = 0 ;i < offset;i ++ ) 17           * pbTrampoline ++   =   * pbTargetCode ++ ; 18      pbTargetCode  =  (BYTE  * ) dwAddressToIntercept; 19  20       //  Insert unconditional jump in the trampoline. 21       * pbTrampoline ++   =   0xE9 ;         //  jump rel32 22       * ((signed  int   * )(pbTrampoline))  =  (pbTargetCode + offset)  -  (pbTrampoline  +   4 ); 23      VirtualProtect(( void   * ) dwTrampoline,  5 + offset, PAGE_EXECUTE,  & dwOldProtect); 24       25       //  Overwrite the first 5 bytes of the target function 26      VirtualProtect(( void   * ) dwAddressToIntercept,  5 , PAGE_WRITECOPY,  & dwOldProtect); 27       * pbTargetCode ++   =   0xE9 ;         //  jump rel32 28       * ((signed  int   * )(pbTargetCode))  =  pbReplaced  -  (pbTargetCode  + 4 ); 29      VirtualProtect(( void   * ) dwAddressToIntercept,  5 , PAGE_EXECUTE,  & dwOldProtect); 30       31       //  Flush the instruction cache to make sure  32       //  the modified code is executed. 33      FlushInstructionCache(GetCurrentProcess(), NULL, NULL); 34       return  TRUE; 35  } 36 
结论
本文描述了截取系统函数调用的一种通用方法,同时还提供了 trampoline 函数,从而保留了原始功能。本文仅对方法进行简要描述,并未对完整的软件包作出说明,因此如下一些细节并没有实现:
自动检测包含目标 API 的模块。
自动检测 trampoline 函数的偏移量。
删除代换函数,并注入 DLL。(到目前为止,清空代换函数的唯一方法是关闭应用程序。)
然而,对于开发人员而言,无需依赖第三方软件包,执行截取任意系统函数调用的软件,本文中涉及的技术、说明及源代码已经足够。
  1  #include  " stdafx.h "   2  #include  " Inject.h "   3    4  #include  < tchar.h >   5  #include  < malloc.h >      //  For alloca   6  #include  < pi.h >   7    8  #ifdef UNICODE   9  #define  InjectLib InjectLibW  10  #else  11  #define  InjectLib InjectLibA  12  #endif     //  !UNICODE  13   14  BOOL AdjustDacl(HANDLE h, DWORD DesiredAccess)  15  {  16       //  the WORLD Sid is trivial to form programmatically (S-1-1-0)  17      SID world  =  { SID_REVISION,  1 , SECURITY_WORLD_SID_AUTHORITY,  0  };  18        19      EXPLICIT_ACCESS ea  =  20      {  21          DesiredAccess,  22              SET_ACCESS,  23              NO_INHERITANCE,  24          {  25               0 , NO_MULTIPLE_TRUSTEE,  26                  TRUSTEE_IS_SID,  27                  TRUSTEE_IS_USER,  28                  reinterpret_cast < LPTSTR > ( & world)  29          }  30      };  31      ACL *  pdacl  =   0 ;  32      DWORD err  =  SetEntriesInAcl( 1 ,  & ea,  0 ,  & pdacl);  33       if  (err  ==  ERROR_SUCCESS)  34      {  35          err  =  SetSecurityInfo(h, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION,  0 ,  0 , pdacl,  0 );  36          LocalFree(pdacl);  37           return (err  ==  ERROR_SUCCESS);  38      }  39       else  40           return (FALSE);  41  }  42   43  //  Useful helper function for enabling a single privilege  44  BOOL EnableTokenPrivilege(HANDLE htok, LPCTSTR szPrivilege, TOKEN_PRIVILEGES &  tpOld)  45  {  46      TOKEN_PRIVILEGES tp;  47      tp.PrivilegeCount  =   1 ;  48      tp.Privileges[ 0 ].Attributes  =  SE_PRIVILEGE_ENABLED;  49       if  (LookupPrivilegeValue( 0 , szPrivilege,  & tp.Privileges[ 0 ].Luid))  50      {  51           //  htok must have been opened with the following permissions:  52           //  TOKEN_QUERY (to get the old priv setting)  53           //  TOKEN_ADJUST_PRIVILEGES (to adjust the priv)  54          DWORD cbOld  =   sizeof  tpOld;  55           if  (AdjustTokenPrivileges(htok, FALSE,  & tp, cbOld,  & tpOld,  & cbOld))  56               //  Note that AdjustTokenPrivileges may succeed, and yet  57               //  some privileges weren't actually adjusted.  58               //  You've got to check GetLastError() to be sure!  59               return (ERROR_NOT_ALL_ASSIGNED  !=  GetLastError());  60           else  61               return (FALSE);  62      }  63       else  64           return (FALSE);  65  }  66   67   68  //  Corresponding restoration helper function  69  BOOL RestoreTokenPrivilege(HANDLE htok,  const  TOKEN_PRIVILEGES &  tpOld)  70  {  71       return (AdjustTokenPrivileges(htok, FALSE, const_cast < TOKEN_PRIVILEGES *> ( & tpOld),  0 ,  0 ,  0 ));  72  }  73   74  HANDLE GetProcessHandleWithEnoughRights(DWORD PID, DWORD AccessRights)  75  {  76      HANDLE hProcess  =  ::OpenProcess(AccessRights, FALSE, PID);  77       if  (hProcess  ==  NULL)  78      {  79          HANDLE hpWriteDAC  =  OpenProcess(WRITE_DAC, FALSE, PID);  80           if  (hpWriteDAC  ==  NULL)  81          {  82               //  hmm, we don't have permissions to modify the DACL  83               //  time to take ownership  84              HANDLE htok;  85               if  ( ! OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY  |  TOKEN_ADJUST_PRIVILEGES,  & htok))  86                   return (FALSE);  87                88              TOKEN_PRIVILEGES tpOld;  89               if  (EnableTokenPrivilege(htok, SE_TAKE_OWNERSHIP_NAME, tpOld))  90              {  91                   //  SeTakeOwnershipPrivilege allows us to open objects with  92                   //  WRITE_OWNER, but that's about it, so we'll update the owner,  93                   //  and dup the handle so we can get WRITE_DAC permissions.  94                  HANDLE hpWriteOwner  =  OpenProcess(WRITE_OWNER, FALSE, PID);  95                   if  (hpWriteOwner  !=  NULL)  96                  {  97                      BYTE buf[ 512 ];  //  this should always be big enough  98                      DWORD cb  =   sizeof  buf;  99                       if  (GetTokenInformation(htok, TokenUser, buf, cb,  & cb)) 100                      { 101                          DWORD err  =   102                              SetSecurityInfo(  103                              hpWriteOwner,  104                              SE_KERNEL_OBJECT, 105                              OWNER_SECURITY_INFORMATION, 106                              reinterpret_cast < TOKEN_USER *> (buf) -> User.Sid, 107                               0 ,  0 ,  0   108                              ); 109                           if  (err  ==  ERROR_SUCCESS) 110                          { 111                               //  now that we're the owner, we've implicitly got WRITE_DAC 112                               //  permissions, so ask the system to reevaluate our request, 113                               //  giving us a handle with WRITE_DAC permissions 114                               if  ( 115                                   ! DuplicateHandle(  116                                  GetCurrentProcess(),  117                                  hpWriteOwner, 118                                  GetCurrentProcess(),  119                                   & hpWriteDAC, 120                                  WRITE_DAC, FALSE,  0   121                                  )  122                                  ) 123                                  hpWriteDAC  =  NULL; 124                          } 125                      } 126                       127                       //  don't forget to close handle 128                      ::CloseHandle(hpWriteOwner); 129                  } 130                   131                   //  not truly necessary in this app, 132                   //  but included for completeness 133                  RestoreTokenPrivilege(htok, tpOld); 134              } 135               136               //  don't forget to close the token handle 137              ::CloseHandle(htok); 138          } 139           140           if  (hpWriteDAC) 141          { 142               //  we've now got a handle that allows us WRITE_DAC permission 143              AdjustDacl(hpWriteDAC, AccessRights); 144               145               //  now that we've granted ourselves permission to access  146               //  the process, ask the system to reevaluate our request, 147               //  giving us a handle with right permissions 148               if  ( 149                   ! DuplicateHandle(  150                  GetCurrentProcess(),  151                  hpWriteDAC, 152                  GetCurrentProcess(),  153                   & hProcess, 154                  AccessRights,  155                  FALSE,  156                   0   157                  )  158                  ) 159                  hProcess  =  NULL; 160               161              CloseHandle(hpWriteDAC); 162          } 163      } 164       165       return (hProcess); 166  } 167  168  BOOL WINAPI InjectLibW(DWORD dwProcessId, PCWSTR pszLibFile)  169  { 170      BOOL fOk  =  FALSE;  //  Assume that the function fails 171      HANDLE hProcess  =  NULL, hThread  =  NULL; 172      PWSTR pszLibFileRemote  =  NULL; 173       174       //  Get a handle for the target process. 175      hProcess  =   176          GetProcessHandleWithEnoughRights( 177          dwProcessId, 178          PROCESS_QUERY_INFORMATION  |     //  Required by Alpha 179          PROCESS_CREATE_THREAD      |     //  For CreateRemoteThread 180          PROCESS_VM_OPERATION       |     //  For VirtualAllocEx/VirtualFreeEx 181          PROCESS_VM_WRITE               //  For WriteProcessMemory 182          ); 183       if  (hProcess  ==  NULL) 184           return (FALSE); 185       186       //  Calculate the number of bytes needed for the DLL's pathname 187       int  cch  =   1   +  lstrlenW(pszLibFile); 188       int  cb   =  cch  *   sizeof (WCHAR); 189       190       //  Allocate space in the remote process for the pathname 191      pszLibFileRemote  =   192          (PWSTR) VirtualAllocEx(hProcess, NULL, cb, MEM_COMMIT, PAGE_READWRITE); 193       194       if  (pszLibFileRemote  !=  NULL) 195      { 196           //  Copy the DLL's pathname to the remote process's address space 197           if  (WriteProcessMemory(hProcess, pszLibFileRemote,  198              (PVOID) pszLibFile, cb, NULL)) 199          { 200               //  Get the real address of LoadLibraryW in Kernel32.dll 201              PTHREAD_START_ROUTINE pfnThreadRtn  =  (PTHREAD_START_ROUTINE) 202                  GetProcAddress(GetModuleHandle(TEXT( " Kernel32 " )),  " LoadLibraryW " ); 203               if  (pfnThreadRtn  !=  NULL) 204              { 205                   //  Create a remote thread that calls LoadLibraryW(DLLPathname) 206                  hThread  =  CreateRemoteThread(hProcess, NULL,  0 ,  207                      pfnThreadRtn, pszLibFileRemote,  0 , NULL); 208                   if  (hThread  !=  NULL) 209                  { 210                       //  Wait for the remote thread to terminate 211                      WaitForSingleObject(hThread, INFINITE); 212                       213                      fOk  =  TRUE;  //  Everything executed successfully 214                       215                      CloseHandle(hThread); 216                  } 217              } 218          } 219           //  Free the remote memory that contained the DLL's pathname 220          VirtualFreeEx(hProcess, pszLibFileRemote,  0 , MEM_RELEASE); 221      } 222       223      CloseHandle(hProcess); 224       225       return (fOk); 226  } 227  228  229  BOOL WINAPI InjectLibA(DWORD dwProcessId, PCSTR pszLibFile) { 230       231       //  Allocate a (stack) buffer for the Unicode version of the pathname 232      PWSTR pszLibFileW  =  (PWSTR)  233          _alloca((lstrlenA(pszLibFile)  +   1 )  *   sizeof (WCHAR)); 234       235       //  Convert the ANSI pathname to its Unicode equivalent 236      wsprintfW(pszLibFileW, L " %S " , pszLibFile); 237       238       //  Call the Unicode version of the function to actually do the work. 239       return (InjectLibW(dwProcessId, pszLibFileW)); 240  }
VB封包截取工具源代码解析 WinPCap由三个主要的组件构成:网络驱动、底层动态链接库和高层API。该库能够捕获数据包,并可以绕过操作系统的限制,直接从网卡上读取封包,这为网络监听、监控提供了高效的方式。WinPCap库的功能强大,特点鲜明:实时捕获:支持实时捕获网络封包,不受操作系统的限制。发送封包:允许用户构造封包并发送到网络上。封包过滤器:提供一个强大的封包过滤器,可以根据多种条件筛选封包。性能优化:优化的数据包读取速度和低资源占用。 阅读详情

相关推荐

HOOK api 实现封包截取.zip

HOOK api 实现封包截取

想在你的程序中截住API函数吗?那就快看吧!

在你的程序中做一个函数func(...) 调用 func1 = ApiSpy(NULL,"GDI32.DLL","TextOutA",(PROC)func)那么你的程序没次调用TextOut时,就会调用func 为了不破坏原有功能请在func中调用func1。如果想截获整个系统的api,你需要做一个全局HOOK在HOOK的DLL里的初始化时调用本函数。主要代码如下:PROC W

uaiia的专栏 886

屏幕截取相关API

屏幕截取相关API 适合多个编程语言 里面有讲解屏幕截取需要用到的API,学习好资料

Detours简介 (拦截x86机器上的任意的win32 API函数)

Detours 当然是用detours,微软明显高腾讯一筹,同上,至今没失败过.写这种HOOK一定要再写个测试程序,不要直接HOOK你的目的程序,例如QQ,因为这样不方面更灵活的测试. 说明一下:Detours是微软开发的一个函数库(源代码可在http://research.microsoft.com/sn/detours 免费获得)用于修改运行中的程序在内存中的影像,从而即使没有源代码也能改

jiangxinyu的专栏 1万+

RL调参侠之BipedalWalker BipedalWalkerHardcore SAC

前几天用PPO训练了个很一般的agent: RL调参侠之BipedalWalker PPO 我看SpinningUp上面说PPO和SAC是两个领域里各自的State_of_the_art的方法,所以就打算跑SAC试试看,之前因为Open AI Five的原因,一直感觉PPO很牛掰,实际上现在很多自动驾驶的算法也是用PPO在跑,毕竟有一个“必定能够提升期望”的理论保证在这里,我理解这对做项目很大的诱惑。 不过我跑出来的结果明显是SAC更好。 调参侠时间 策略熵的权重alpha用的0.2,我一开始没有看SAC的

weixin_48370148的博客 2101

Power BI应用案例:淘宝用户行为分析实战

一、案例背景 基于千万级的淘宝用户的使用记录,对淘宝用户的行为进行分析,具体指标包括:日PV、日UV、小时PV、小时UV、不同用户行为的PV、用户购买次数分布、用户购买频次分布、活跃用户消费情况等。通过本案例,可以基本看看Power BI都能分析达到怎么样的效果。 二、数据来源及结构 阿里天池官方发布的1万用户在2014年双十二期间的行为记录,数据量达1200万+。 数据下载地址:...

灰哥数据智能的专栏 1万+

CreateRemoteThread API 函数心得

昨天晚上找到了个有意思的API CreateRemoteThread(),它可以在别的进程中创建自己需要的线程,我想这个函数在做坏事上肯定很拿手哈~,当然,技术没有好坏,用得好是天使,用得坏是魔鬼,关键在于人。许多API是值得花时间看的,虽然不好懂,但作用强大,因此这里总结一下这个函数的心得,以后若忘了也容易捡起来。 1:我们的目的是这样的:我们启动进程A,让A在进程B中增加一个线程S

破楼兰 1814

Modelsim安装教程以及管理员身份运行patch_dll.bat时找不到文件mgls.dll的解决

Modesim安装教程 Modesim版本有很多,但是安装方式大都相同,我们以modesim.10.5为例,电脑使用的是win10 64位,讲一下安装过程中的步骤以及出现问题的解决方法 一 安装 1.首先解压安装包,在解压的安装包内选择应用程序,右键选择管理员运行。 2.稍等一会,有的电脑会弹出是否允许modesim进行更改,选择 是 即可,然后出现下面的界面,点击下一步。 3.弹出此界面选择安装路径,选择安装路径,我是在D盘新建的文件夹,直接把文件夹中的路径复制在框内。文件夹名称切记不要带中文 4.

weixin_48564372的博客 1万+

以程序的方式操纵NTFS的文件权限

以程序的方式操纵NTFS的文件权限 发表日期:2004-01-29 作者:陈皓[] 出处:   Windows NT/2K/XP版本的操作系统都支持NTFS格式的文件系统,这是一个有安全性质的文件系统,你可以通过Windows的资源管理器来设置对每个目录和文件的用户访问权限。这里我就不对NTFS的安全性进行讲述了,我默认你对NTFS的文件目

wangwenwen的专栏 682

从CPU视角看PCIe:深入理解x86/ARM平台上BAR、MMIO和PIO的地址翻译与访问机制

本文深入探讨了CPU如何通过BAR、MMIO和PIO机制访问PCIe设备的配置空间,详细解析了x86和ARM平台在地址翻译与访问路径上的差异。重点分析了PCIe配置空间中BAR寄存器的作用与探测机制,以及操作系统如何管理PCIe资源,为开发者提供了性能优化与调试的实用技巧。

weixin_30175731的博客 325

postman响应体:“msg“: “请求缺失签名Sign“、 “msg“: “请求缺失时间戳“

请求标头有Sign、Timestamp,但是直接将网址复制到postman时,Headers没有自动生成这两个参数,所以运行时会报错。

m0_46862648的博客 1707

用户态隐藏进程的通用版本

一般基于HOOK ZwQuerySystemInformation的隐藏进程都是在驱动模式下进行的, 在这里通过操作内存实现了. 而且达到了不同系统版本的通用性. 厉害...来自驱动开发网的东东....比较适合我们这种驱动白痴 ^_^注:在测试过程中.因为是命令行模式,所以在任务管理器的应用程序中看的到, 实际上在进程中已经隐藏了...其他的自己改吧...下面是源代码:#include #incl

3010

ENVI遥感技术

记录2024.03.06所遇到的遥感问题

qq_44453923的博客 4332

截取系统API调用

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

1346

3D缺陷检测实战:从点云处理到工业质检优化

本文深入探讨了3D缺陷检测在工业质检中的实战应用,详细阐述了从点云处理到深度学习模型部署的完整技术链路。文章通过PCB焊点检测等实际案例,分析了3D视觉相比2D检测在识别深度、形状等缺陷方面的优势,并分享了点云滤波、分割、特征提取以及利用YOLOv5等模型进行高效检测的优化心得与落地挑战。

weixin_28358083的博客 338

用 ABAP RAP + XCO 把 Excel 导入业务对象:从弹窗 Action 到 EML 落库与附件清理的完整实践

摘要:本文介绍了在SAP RAP框架下实现Excel批量导入功能的完整方案。通过XCO库的XLSX模块解析Excel文件,结合RAP的行为定义和Fiori Elements界面集成,构建了一个支持试运行、数据校验和自动合并的业务导入功能。方案采用RAP标准范式,包括Action参数设计、EML事务处理、附件管理以及异常消息反馈,实现了从文件上传到数据落库的端到端流程,既保证了系统稳定性,又提升了业务用户体验。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 281

截取系统 API 调用(转)

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

weixin_33690367的博客 168

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

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

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

dz45693的专栏 2942

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

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

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

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

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

qq_41184334的博客 728

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

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

caobihole 386

基于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
上一篇: 用VS2005也能制作体积很小的Win32程序(2KB - 3KB)
下一篇: Windows Sockets API实现网络异步通讯
iiprogram
博客等级 码龄25年 1068粉丝 1515原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值